Initial integration of updated ZynAddSubFX

This commit is contained in:
Tobias Doerffel
2014-02-18 19:56:12 +01:00
parent f969bd4650
commit 9209ef59e3
198 changed files with 128 additions and 66605 deletions

View File

@@ -128,7 +128,7 @@ const int MidiControllerCount = 128;
const int MidiProgramCount = 128;
const int MidiMaxVelocity = 127;
const int MidiMaxControllerValue = 127;
const int MidiMaxNote = 127;
const int MidiMaxKey = 127;
const int MidiMaxPanning = 127;
const int MidiMinPanning = -128;

View File

@@ -1,26 +1,5 @@
INCLUDE(BuildPlugin)
SET(ZYN_SRC_GUI
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/MasterUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/VirKeyboard.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/ConfigUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/OscilGenUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/WidgetPDial.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/ResonanceUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/MicrotonalUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/ADnoteUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/PresetsUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/EffUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/FilterUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/PartUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/EnvelopeUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/LFOUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/SeqUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/PADnoteUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/SUBnoteUI.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/UI/BankUI.cc"
)
# definitions for ZynAddSubFX
IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE)
@@ -48,42 +27,80 @@ ENDIF(LMMS_BUILD_WIN32)
SET(FLTK_SKIP_OPENGL TRUE)
SET(FLTK_SKIP_FORMS TRUE)
SET(FLTK_SKIP_IMAGES TRUE)
SET(FLTK_SKIP_FLUID TRUE)
SET(FLTK_SKIP_MATH TRUE)
IF(MINGW_PREFIX)
SET(FLTK_SKIP_FLUID TRUE)
ENDIF()
FIND_PACKAGE(FLTK REQUIRED)
IF(MINGW_PREFIX)
SET(FLTK_FLUID_EXECUTABLE "${MINGW_PREFIX}/bin/fluid")
ENDIF()
INCLUDE_DIRECTORIES("${FLTK_INCLUDE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
${FFTW3F_INCLUDE_DIRS}
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_BINARY_DIR}")
set(ZASF_CORE_LIBS
zynaddsubfx_input
zynaddsubfx_output
zynaddsubfx_misc
zynaddsubfx_synth
zynaddsubfx_seq
zynaddsubfx_effect
zynaddsubfx_params
zynaddsubfx_dsp
zynaddsubfx_samples
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/zynaddsubfx/src/UI)
add_subdirectory(zynaddsubfx/src/Nio)
add_subdirectory(zynaddsubfx/src/UI)
SET(zynaddsubfx_core_SRCS
zynaddsubfx/src/DSP/AnalogFilter.cpp
zynaddsubfx/src/DSP/FFTwrapper.cpp
zynaddsubfx/src/DSP/Filter.cpp
zynaddsubfx/src/DSP/FormantFilter.cpp
zynaddsubfx/src/DSP/SVFilter.cpp
zynaddsubfx/src/DSP/Unison.cpp
zynaddsubfx/src/Effects/Alienwah.cpp
zynaddsubfx/src/Effects/Chorus.cpp
zynaddsubfx/src/Effects/Distorsion.cpp
zynaddsubfx/src/Effects/DynamicFilter.cpp
zynaddsubfx/src/Effects/Echo.cpp
zynaddsubfx/src/Effects/Effect.cpp
zynaddsubfx/src/Effects/EffectLFO.cpp
zynaddsubfx/src/Effects/EffectMgr.cpp
zynaddsubfx/src/Effects/EQ.cpp
zynaddsubfx/src/Effects/Phaser.cpp
zynaddsubfx/src/Effects/Reverb.cpp
zynaddsubfx/src/Misc/Bank.cpp
zynaddsubfx/src/Misc/Config.cpp
zynaddsubfx/src/Misc/Dump.cpp
zynaddsubfx/src/Misc/Master.cpp
zynaddsubfx/src/Misc/Microtonal.cpp
zynaddsubfx/src/Misc/Part.cpp
zynaddsubfx/src/Misc/Util.cpp
zynaddsubfx/src/Misc/QtXmlWrapper.cpp
zynaddsubfx/src/Misc/Recorder.cpp
zynaddsubfx/src/Misc/WavFile.cpp
zynaddsubfx/src/Misc/WaveShapeSmps.cpp
zynaddsubfx/src/Params/ADnoteParameters.cpp
zynaddsubfx/src/Params/Controller.cpp
zynaddsubfx/src/Params/EnvelopeParams.cpp
zynaddsubfx/src/Params/FilterParams.cpp
zynaddsubfx/src/Params/LFOParams.cpp
zynaddsubfx/src/Params/PADnoteParameters.cpp
zynaddsubfx/src/Params/Presets.cpp
zynaddsubfx/src/Params/PresetsArray.cpp
zynaddsubfx/src/Params/PresetsStore.cpp
zynaddsubfx/src/Params/SUBnoteParameters.cpp
zynaddsubfx/src/Synth/SynthNote.cpp
zynaddsubfx/src/Synth/ADnote.cpp
zynaddsubfx/src/Synth/Envelope.cpp
zynaddsubfx/src/Synth/LFO.cpp
zynaddsubfx/src/Synth/OscilGen.cpp
zynaddsubfx/src/Synth/PADnote.cpp
zynaddsubfx/src/Synth/Resonance.cpp
zynaddsubfx/src/Synth/SUBnote.cpp
)
macro(unit_test NAME CXX_FILE FILES)
endmacro(unit_test)
add_subdirectory(src/Misc)
add_subdirectory(src/Input)
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)
TARGET_LINK_LIBRARIES(ZynAddSubFxCore ${ZASF_CORE_LIBS} ${FFTW3F_LIBRARIES} ${QT_LIBRARIES} -lz -lpthread)
ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS})
TARGET_LINK_LIBRARIES(ZynAddSubFxCore zynaddsubfx_nio ${FFTW3F_LIBRARIES} ${QT_LIBRARIES} -lz -lpthread)
IF(LMMS_BUILD_WIN32)
TARGET_LINK_LIBRARIES(ZynAddSubFxCore -lws2_32)
INSTALL(TARGETS ZynAddSubFxCore RUNTIME DESTINATION "${PLUGIN_DIR}")
@@ -106,12 +123,11 @@ ENDIF(WIN32)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp ${ZYN_SRC_GUI} "${WINRC}")
ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp "${WINRC}")
INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION "${PLUGIN_DIR}")
TARGET_LINK_LIBRARIES(RemoteZynAddSubFx ${FLTK_LIBRARIES} -lpthread "-L\"${CMAKE_CURRENT_BINARY_DIR}\"" -lZynAddSubFxCore )
ADD_DEPENDENCIES(RemoteZynAddSubFx ZynAddSubFxCore)
TARGET_LINK_LIBRARIES(RemoteZynAddSubFx zynaddsubfx_gui ZynAddSubFxCore ${FLTK_LIBRARIES} -lpthread )
# link system libraries when on win32
# link Qt libraries when on win32
IF(LMMS_BUILD_WIN32)
TARGET_LINK_LIBRARIES(RemoteZynAddSubFx ${QT_LIBRARIES})
ENDIF(LMMS_BUILD_WIN32)

View File

@@ -24,19 +24,25 @@
#include <lmmsconfig.h>
#include "zynaddsubfx/src/Misc/Util.h"
#include <unistd.h>
#include "LocalZynAddSubFx.h"
#include "src/Input/NULLMidiIn.h"
#include "src/Misc/Master.h"
#include "src/Misc/Dump.h"
#include "zynaddsubfx/src/Nio/NulEngine.h"
#include "zynaddsubfx/src/Misc/Master.h"
#include "zynaddsubfx/src/Misc/Part.h"
#include "zynaddsubfx/src/Misc/Dump.h"
SYNTH_T* synth = NULL;
int LocalZynAddSubFx::s_instanceCount = 0;
LocalZynAddSubFx::LocalZynAddSubFx()
LocalZynAddSubFx::LocalZynAddSubFx() :
m_master( NULL ),
m_ioEngine( new NulEngine )
{
for( int i = 0; i < NumKeys; ++i )
{
@@ -53,15 +59,19 @@ LocalZynAddSubFx::LocalZynAddSubFx()
initConfig();
OSCIL_SIZE = config.cfg.OscilSize;
synth = new SYNTH_T;
synth->oscilsize = config.cfg.OscilSize;
synth->alias();
srand( time( NULL ) );
denormalkillbuf = new REALTYPE[SOUND_BUFFER_SIZE];
for( int i = 0; i < SOUND_BUFFER_SIZE; ++i )
denormalkillbuf = new float[synth->buffersize];
for( int i = 0; i < synth->buffersize; ++i )
{
denormalkillbuf[i] = (RND-0.5)*1e-16;
}
}
++s_instanceCount;
m_master = new Master();
@@ -94,17 +104,19 @@ void LocalZynAddSubFx::initConfig()
void LocalZynAddSubFx::setSampleRate( int _sampleRate )
void LocalZynAddSubFx::setSampleRate( int sampleRate )
{
SAMPLE_RATE = _sampleRate;
synth->samplerate = sampleRate;
synth->alias();
}
void LocalZynAddSubFx::setBufferSize( int _bufferSize )
void LocalZynAddSubFx::setBufferSize( int bufferSize )
{
SOUND_BUFFER_SIZE = _bufferSize;
synth->buffersize = bufferSize;
synth->alias();
}
@@ -160,14 +172,12 @@ void LocalZynAddSubFx::setPresetDir( const std::string & _dir )
m_presetsDir = _dir;
for( int i = 0; i < MAX_BANK_ROOT_DIRS; ++i )
{
if( config.cfg.bankRootDirList[i] == NULL )
if( config.cfg.bankRootDirList[i].empty() )
{
config.cfg.bankRootDirList[i] = new char[MAX_STRING_SIZE];
strcpy( config.cfg.bankRootDirList[i], m_presetsDir.c_str() );
config.cfg.bankRootDirList[i] = m_presetsDir;
break;
}
else if( strcmp( config.cfg.bankRootDirList[i],
m_presetsDir.c_str() ) == 0 )
else if( config.cfg.bankRootDirList[i] == m_presetsDir )
{
break;
}
@@ -192,41 +202,38 @@ void LocalZynAddSubFx::setLmmsWorkingDir( const std::string & _dir )
void LocalZynAddSubFx::processMidiEvent( const MidiEvent& event )
{
// all functions are called while m_master->mutex is held
static NULLMidiIn midiIn;
switch( event.type() )
{
case MidiNoteOn:
if( event.velocity() > 0 )
{
if( event.key() <= 0 || event.key() >= 128 )
if( event.key() < 0 || event.key() > MidiMaxKey )
{
break;
}
if( m_runningNotes[event.key()] > 0 )
{
m_master->NoteOff( event.channel(), event.key() );
m_master->noteOff( event.channel(), event.key() );
}
++m_runningNotes[event.key()];
m_master->NoteOn( event.channel(), event.key(), event.velocity() );
m_master->noteOn( event.channel(), event.key(), event.velocity() );
break;
}
case MidiNoteOff:
if( event.key() <= 0 || event.key() >= 128 )
if( event.key() < 0 || event.key() > MidiMaxKey )
{
break;
}
if( --m_runningNotes[event.key()] <= 0 )
{
m_master->NoteOff( event.channel(), event.key() );
m_master->noteOff( event.channel(), event.key() );
}
break;
case MidiPitchBend:
m_master->SetController( event.channel(), C_pitchwheel, event.pitchBend()-8192 );
m_master->setController( event.channel(), C_pitchwheel, event.pitchBend()-8192 );
break;
case MidiControlChange:
m_master->SetController( event.channel(), midiIn.getcontroller( event.controllerNumber() ), event.controllerValue() );
m_master->setController( event.channel(), event.controllerNumber(), event.controllerValue() );
break;
default:
break;
@@ -238,12 +245,13 @@ void LocalZynAddSubFx::processMidiEvent( const MidiEvent& event )
void LocalZynAddSubFx::processAudio( sampleFrame * _out )
{
REALTYPE outputl[SOUND_BUFFER_SIZE];
REALTYPE outputr[SOUND_BUFFER_SIZE];
float outputl[synth->buffersize];
float outputr[synth->buffersize];
m_master->AudioOut( outputl, outputr );
for( int f = 0; f < SOUND_BUFFER_SIZE; ++f )
// TODO: move to MixHelpers
for( int f = 0; f < synth->buffersize; ++f )
{
_out[f][0] = outputl[f];
_out[f][1] = outputr[f];

View File

@@ -29,6 +29,7 @@
#include "note.h"
class Master;
class NulEngine;
class LocalZynAddSubFx
{
@@ -66,6 +67,7 @@ protected:
int m_runningNotes[NumKeys];
Master * m_master;
NulEngine* m_ioEngine;
} ;

View File

@@ -35,7 +35,7 @@
#include "RemoteZynAddSubFx.h"
#include "LocalZynAddSubFx.h"
#include "src/UI/MasterUI.h"
#include "zynaddsubfx/src/UI/MasterUI.h"
#include <FL/x.H>
@@ -282,3 +282,22 @@ int main( int _argc, char * * _argv )
}
#ifdef NTK_GUI
static Fl_Tiled_Image *module_backdrop;
#endif
void set_module_parameters ( Fl_Widget *o )
{
#ifdef NTK_GUI
o->box( FL_DOWN_FRAME );
o->align( o->align() | FL_ALIGN_IMAGE_BACKDROP );
o->color( FL_BLACK );
o->image( module_backdrop );
o->labeltype( FL_SHADOW_LABEL );
#else
o->box( FL_PLASTIC_UP_BOX );
o->color( FL_CYAN );
o->labeltype( FL_EMBOSSED_LABEL );
#endif
}

View File

@@ -32,7 +32,7 @@
#include "Instrument.h"
#include "InstrumentView.h"
#include "RemotePlugin.h"
#include "src/globals.h"
#include "zynaddsubfx/src/globals.h"
class QPushButton;

View File

@@ -1,450 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
AnalogFilter.cpp - 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);
}

View File

@@ -1,82 +0,0 @@
/*
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
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 ANALOG_FILTER_H
#define ANALOG_FILTER_H
#include "../globals.h"
#include "Filter_.h"
/**Implementation of Several analog filters (lowpass, highpass...)*/
class AnalogFilter:public Filter_
{
public:
AnalogFilter(unsigned char Ftype,
REALTYPE Ffreq,
REALTYPE Fq,
unsigned char Fstages);
~AnalogFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency, REALTYPE q_);
void setq(REALTYPE q_);
void settype(int type_);
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;
} x[MAX_FILTER_STAGES + 1], y[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();
int type; //The type of the filter (LPF1,HPF1,LPF2,HPF2...)
int stages; //how many times the filter is applied (0->1,1->2,etc.)
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
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; /**\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)
};
#endif

View File

@@ -1,14 +0,0 @@
set(zynaddsubfx_dsp_SRCS
AnalogFilter.cpp
FFTwrapper.cpp
Filter.cpp
FormantFilter.cpp
SVFilter.cpp
Unison.cpp
)
add_library(zynaddsubfx_dsp STATIC
${zynaddsubfx_dsp_SRCS}
)
target_link_libraries(zynaddsubfx_dsp)

View File

@@ -1,136 +0,0 @@
/*
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
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 "FFTwrapper.h"
FFTwrapper::FFTwrapper(int fftsize_)
{
fftsize = fftsize_;
tmpfftdata1 = new fftw_real[fftsize];
tmpfftdata2 = new fftw_real[fftsize];
#ifdef FFTW_VERSION_2
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()
{
#ifdef FFTW_VERSION_2
rfftw_destroy_plan(planfftw);
rfftw_destroy_plan(planfftw_inv);
#else
fftwf_destroy_plan(planfftw);
fftwf_destroy_plan(planfftw_inv);
#endif
delete [] tmpfftdata1;
delete [] tmpfftdata2;
}
/*
* do the Fast Fourier Transform
*/
void FFTwrapper::smps2freqs(REALTYPE *smps, FFTFREQS freqs)
{
#ifdef FFTW_VERSION_2
for(int i = 0; i < fftsize; i++)
tmpfftdata1[i] = smps[i];
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];
}
#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];
}
#endif
tmpfftdata2[fftsize / 2] = 0.0;
}
/*
* do the Inverse Fast Fourier Transform
*/
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];
}
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];
}
fftwf_execute(planfftw_inv);
for(int i = 0; i < fftsize; i++)
smps[i] = tmpfftdata2[i];
#endif
}
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;
}
}
void deleteFFTFREQS(FFTFREQS *f)
{
delete[] f->c;
delete[] f->s;
f->c = f->s = NULL;
}

View File

@@ -1,70 +0,0 @@
/*
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
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 FFT_WRAPPER_H
#define FFT_WRAPPER_H
#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
/**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;
};
void newFFTFREQS(FFTFREQS *f, int size);
void deleteFFTFREQS(FFTFREQS *f);
#endif

View File

@@ -1,87 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Filter.cpp - 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
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 "Filter.h"
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;
}
}
Filter::~Filter()
{
delete (filter);
}
void Filter::filterout(REALTYPE *smp)
{
filter->filterout(smp);
}
void Filter::setfreq(REALTYPE frequency)
{
filter->setfreq(frequency);
}
void Filter::setfreq_and_q(REALTYPE frequency, REALTYPE q_)
{
filter->setfreq_and_q(frequency, q_);
}
void Filter::setq(REALTYPE q_)
{
filter->setq(q_);
}
REALTYPE Filter::getrealfreq(REALTYPE freqpitch)
{
if((category == 0) || (category == 2))
return pow(2.0, freqpitch + 9.96578428); //log2(1000)=9.95748
else
return freqpitch;
}

View File

@@ -1,52 +0,0 @@
/*
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
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 FILTER_H
#define FILTER_H
#include "../globals.h"
#include "Filter_.h"
#include "AnalogFilter.h"
#include "FormantFilter.h"
#include "SVFilter.h"
#include "../Params/FilterParams.h"
class Filter
{
public:
Filter(FilterParams *pars);
~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:
Filter_ *filter;
unsigned char category;
};
#endif

View File

@@ -1,43 +0,0 @@
/*
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
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 FILTER__H
#define FILTER__H
#include "../globals.h"
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) = 0;
REALTYPE outgain;
private:
};
#endif

View File

@@ -1,231 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
FormantFilter.cpp - 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::setgain(REALTYPE dBgain)
{}
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;
}
}

View File

@@ -1,69 +0,0 @@
/*
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
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 FORMANT_FILTER_H
#define FORMANT_FILTER_H
#include "../globals.h"
#include "Filter_.h"
#include "AnalogFilter.h"
#include "../Params/FilterParams.h"
class FormantFilter:public Filter_
{
public:
FormantFilter(FilterParams *pars);
~FormantFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency, REALTYPE q_);
void setq(REALTYPE q_);
void setgain(REALTYPE dBgain);
void cleanup();
private:
AnalogFilter *formant[FF_MAX_FORMANTS];
REALTYPE *inbuffer, *tmpbuf;
struct {
REALTYPE freq, amp, q; //frequency,amplitude,Q
} formantpar[FF_MAX_VOWELS][FF_MAX_FORMANTS],
currentformants[FF_MAX_FORMANTS];
struct {
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);
};
#endif

View File

@@ -1,186 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
SVFilter.cpp - 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
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 "SVFilter.h"
SVFilter::SVFilter(unsigned char Ftype,
REALTYPE Ffreq,
REALTYPE Fq,
unsigned char Fstages)
{
stages = Fstages;
type = Ftype;
freq = Ffreq;
q = Fq;
gain = 1.0;
outgain = 1.0;
needsinterpolation = 0;
firsttime = 1;
if(stages >= MAX_FILTER_STAGES)
stages = MAX_FILTER_STAGES;
cleanup();
setfreq_and_q(Ffreq, Fq);
}
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;
}
oldabovenq = 0;
abovenq = 0;
}
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;
par.q = pow(par.q, 1.0 / (stages + 1));
par.q_sqrt = sqrt(par.q);
}
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);
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;
}
freq = frequency;
computefiltercoefs();
firsttime = 0;
}
void SVFilter::setfreq_and_q(REALTYPE frequency, REALTYPE q_)
{
q = q_;
setfreq(frequency);
}
void SVFilter::setq(REALTYPE q_)
{
q = q_;
computefiltercoefs();
}
void SVFilter::settype(int type_)
{
type = type_;
computefiltercoefs();
}
void SVFilter::setgain(REALTYPE dBgain)
{
gain = dB2rap(dBgain);
computefiltercoefs();
}
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)
{
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;
}
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)
{
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);
}
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;
}
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
smp[i] *= outgain;
}

View File

@@ -1,71 +0,0 @@
/*
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
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 SV_FILTER_H
#define SV_FILTER_H
#include "../globals.h"
#include "Filter_.h"
class SVFilter:public Filter_
{
public:
SVFilter(unsigned char Ftype,
REALTYPE Ffreq,
REALTYPE Fq,
unsigned char Fstages);
~SVFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency, REALTYPE q_);
void setq(REALTYPE q_);
void settype(int type_);
void setgain(REALTYPE dBgain);
void setstages(int stages_);
void cleanup();
private:
struct fstage {
REALTYPE low, high, band, notch;
} st[MAX_FILTER_STAGES + 1];
struct parameters {
REALTYPE f, q, q_sqrt;
} par, ipar;
void singlefilterout(REALTYPE *smp, fstage &x, parameters &par);
void computefiltercoefs();
int type; //The type of the filter (LPF1,HPF1,LPF2,HPF2...)
int stages; //how many times the filter is applied (0->1,1->2,etc.)
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;
};
#endif

View File

@@ -1,184 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Unison.cpp - Unison effect (multivoice chorus)
Copyright (C) 2002-2009 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 "Unison.h"
Unison::Unison(int update_period_samples_, REALTYPE max_delay_sec_) {
update_period_samples = update_period_samples_;
max_delay = (int)(max_delay_sec_ * (REALTYPE)SAMPLE_RATE + 1);
if(max_delay < 10)
max_delay = 10;
delay_buffer = new REALTYPE[max_delay];
delay_k = 0;
base_freq = 1.0;
unison_bandwidth_cents = 10.0;
ZERO_REALTYPE(delay_buffer, max_delay);
uv = NULL;
update_period_sample_k = 0;
first_time = 0;
set_size(1);
}
Unison::~Unison() {
delete [] delay_buffer;
if(uv)
delete [] uv;
}
void Unison::set_size(int new_size) {
if(new_size < 1)
new_size = 1;
unison_size = new_size;
if(uv)
delete [] uv;
uv = new UnisonVoice[unison_size];
first_time = true;
update_parameters();
}
void Unison::set_base_frequency(REALTYPE freq) {
base_freq = freq;
update_parameters();
}
void Unison::set_bandwidth(REALTYPE bandwidth) {
if(bandwidth < 0)
bandwidth = 0.0;
if(bandwidth > 1200.0)
bandwidth = 1200.0;
//printf("bandwidth %g\n", bandwidth);
unison_bandwidth_cents = bandwidth;
update_parameters();
}
void Unison::update_parameters() {
if(!uv)
return;
REALTYPE increments_per_second = SAMPLE_RATE
/ (REALTYPE) update_period_samples;
// printf("#%g, %g\n",increments_per_second,base_freq);
for(int i = 0; i < unison_size; i++) {
REALTYPE base = pow(UNISON_FREQ_SPAN, RND * 2.0 - 1.0);
uv[i].relative_amplitude = base;
REALTYPE period = base / base_freq;
REALTYPE m = 4.0 / (period * increments_per_second);
if(RND < 0.5)
m = -m;
uv[i].step = m;
// printf("%g %g\n",uv[i].relative_amplitude,period);
}
REALTYPE max_speed = pow(2.0, unison_bandwidth_cents / 1200.0);
unison_amplitude_samples = 0.125
* (max_speed - 1.0) * SAMPLE_RATE / base_freq;
//printf("unison_amplitude_samples %g\n", unison_amplitude_samples);
if(unison_amplitude_samples >= max_delay - 1)
unison_amplitude_samples = max_delay - 2;
update_unison_data();
}
void Unison::process(int bufsize, REALTYPE *inbuf, REALTYPE *outbuf) {
if(!uv)
return;
if(!outbuf)
outbuf = inbuf;
REALTYPE volume = 1.0 / sqrt(unison_size);
REALTYPE xpos_step = 1.0 / (REALTYPE) update_period_samples;
REALTYPE xpos = (REALTYPE) update_period_sample_k * xpos_step;
for(int i = 0; i < bufsize; i++) {
if((update_period_sample_k++) >= update_period_samples) {
update_unison_data();
update_period_sample_k = 0;
xpos = 0.0;
}
xpos += xpos_step;
REALTYPE in = inbuf[i], out = 0.0;
REALTYPE sign = 1.0;
for(int k = 0; k < unison_size; k++) {
REALTYPE vpos = uv[k].realpos1
* (1.0 - xpos) + uv[k].realpos2 * xpos; //optimize
REALTYPE pos = delay_k + max_delay - vpos - 1.0; //optimize
int posi;
REALTYPE posf;
F2I(pos, posi); //optimize!
if(posi >= max_delay)
posi -= max_delay;
posf = pos - floor(pos);
out +=
((1.0
- posf) * delay_buffer[posi] + posf
* delay_buffer[posi + 1]) * sign;
sign = -sign;
}
outbuf[i] = out * volume;
// printf("%d %g\n",i,outbuf[i]);
delay_buffer[delay_k] = in;
if((++delay_k) >= max_delay)
delay_k = 0;
}
}
void Unison::update_unison_data() {
if(!uv)
return;
for(int k = 0; k < unison_size; k++) {
REALTYPE pos = uv[k].position;
REALTYPE step = uv[k].step;
pos += step;
if(pos <= -1.0) {
pos = -1.0;
step = -step;
}
if(pos >= 1.0) {
pos = 1.0;
step = -step;
}
REALTYPE vibratto_val = (pos - 0.333333333 * pos * pos * pos) * 1.5; //make the vibratto lfo smoother
REALTYPE newval = 1.0 + 0.5
* (vibratto_val
+ 1.0) * unison_amplitude_samples
* uv[k].relative_amplitude;
if(first_time)
uv[k].realpos1 = uv[k].realpos2 = newval;
else{
uv[k].realpos1 = uv[k].realpos2;
uv[k].realpos2 = newval;
}
uv[k].position = pos;
uv[k].step = step;
}
if(first_time)
first_time = false;
}

View File

@@ -1,69 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Unison.h - Unison effect (multivoice chorus)
Copyright (C) 2002-2009 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 UNISON_H
#define UNISON_H
#include <stdlib.h>
#include "../globals.h"
#define UNISON_FREQ_SPAN 2.0
//how much the unison frequencies varies (always >= 1.0)
class Unison
{
public:
Unison(int update_period_samples_, REALTYPE max_delay_sec_);
~Unison();
void set_size(int new_size);
void set_base_frequency(REALTYPE freq);
void set_bandwidth(REALTYPE bandwidth_cents);
void process(int bufsize, REALTYPE *inbuf, REALTYPE *outbuf = NULL);
private:
void update_parameters();
void update_unison_data();
int unison_size;
REALTYPE base_freq;
struct UnisonVoice {
REALTYPE step, position; //base LFO
REALTYPE realpos1, realpos2; //the position regarding samples
REALTYPE relative_amplitude;
REALTYPE lin_fpos, lin_ffreq;
UnisonVoice() {
position = RND * 1.8 - 0.9;
realpos1 = 0.0;
realpos2 = 0.0;
step = 0.0;
relative_amplitude = 1.0;
}
} *uv;
int update_period_samples, update_period_sample_k;
int max_delay, delay_k;
bool first_time;
REALTYPE *delay_buffer;
REALTYPE unison_amplitude_samples;
REALTYPE unison_bandwidth_cents;
};
#endif

View File

@@ -1,281 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Alienwah.cpp - "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
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 "Alienwah.h"
Alienwah::Alienwah(const int &insertion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), oldl(NULL), oldr(NULL)
{
setpreset(Ppreset);
cleanup();
oldclfol = complex<REALTYPE>(fb, 0.0);
oldclfor = complex<REALTYPE>(fb, 0.0);
}
Alienwah::~Alienwah()
{
if(oldl != NULL)
delete [] oldl;
if(oldr != NULL)
delete [] oldr;
}
/*
* Apply the effect
*/
void Alienwah::out(const Stereo<float *> &smp)
{
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
* utilized.
* 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;
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++) {
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)) * smp.l[i] * (1.0 - panning);
oldl[oldk] = out;
REALTYPE l = out.real() * 10.0 * (fb + 0.1);
//right
tmp = clfor * x + oldclfor * x1;
out = tmp * oldr[oldk];
out.real() += (1 - fabs(fb)) * smp.r[i] * (1.0 - panning);
oldr[oldk] = out;
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;
}
oldclfol = clfol;
oldclfor = clfor;
}
/*
* Cleanup the effect
*/
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;
}
/*
* Parameter control
*/
void Alienwah::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = (Pdepth / 127.0);
}
void Alienwah::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
fb = fabs((Pfb - 64.0) / 64.1);
fb = sqrt(fb);
if(fb < 0.4)
fb = 0.4;
if(Pfb < 64)
fb = -fb;
}
void Alienwah::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void Alienwah::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
void Alienwah::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
}
void Alienwah::setphase(unsigned char Pphase)
{
this->Pphase = Pphase;
phase = (Pphase - 64.0) / 64.0 * PI;
}
void Alienwah::setdelay(unsigned char Pdelay)
{
if(oldl != NULL)
delete [] oldl;
if(oldr != NULL)
delete [] oldr;
if(Pdelay >= MAX_ALIENWAH_DELAY)
this->Pdelay = MAX_ALIENWAH_DELAY;
else
this->Pdelay = Pdelay;
oldl = new complex<REALTYPE>[Pdelay];
oldr = new complex<REALTYPE>[Pdelay];
cleanup();
}
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}
};
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
Ppreset = npreset;
}
void Alienwah::changepar(int npar, 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(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;
}
}

View File

@@ -1,85 +0,0 @@
/*
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
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 ALIENWAH_H
#define ALIENWAH_H
#include <complex>
#include "../globals.h"
#include "Effect.h"
#include "EffectLFO.h"
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(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
void changepar(int npar, unsigned char value);
unsigned char getpar(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;
//Control Parameters
void setvolume(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setdepth(unsigned char Pdepth);
void setfb(unsigned char Pfb);
void setlrcross(unsigned char Plrcross);
void setdelay(unsigned char Pdelay);
void setphase(unsigned char Pphase);
//Internal Values
REALTYPE panning, fb, depth, lrcross, phase;
complex<REALTYPE> *oldl, *oldr;
complex<REALTYPE> oldclfol, oldclfor;
int oldk;
};
#endif

View File

@@ -1,19 +0,0 @@
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)

View File

@@ -1,320 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Chorus.cpp - 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;
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.cpp::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n";
result = maxdelay - 1.0;
}
return result;
}
void Chorus::out(const Stereo<float *> &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 < SOUND_BUFFER_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 < 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()
{
delaySample.l.clear();
delaySample.r.clear();
}
/*
* Parameter control
*/
void Chorus::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = (pow(8.0, (Pdepth / 127.0) * 2.0) - 1.0) / 1000.0; //seconds
}
void Chorus::setdelay(unsigned char Pdelay)
{
this->Pdelay = Pdelay;
delay = (pow(10.0, (Pdelay / 127.0) * 2.0) - 1.0) / 1000.0; //seconds
}
void Chorus::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
fb = (Pfb - 64.0) / 64.1;
}
void Chorus::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void Chorus::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
void Chorus::setlrcross(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(int npar, 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(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;
}
}

View File

@@ -1,114 +0,0 @@
/*
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
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 CHORUS_H
#define CHORUS_H
#include "../globals.h"
#include "Effect.h"
#include "EffectLFO.h"
#include "../Samples/Sample.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(const Stereo<float *> &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(int npar, 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(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
//Parameter Controls
void setvolume(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setdepth(unsigned char Pdepth);
void setdelay(unsigned char Pdelay);
void setfb(unsigned char Pfb);
void setlrcross(unsigned char Plrcross);
//Internal Values
REALTYPE depth, delay, fb, lrcross, panning;
REALTYPE dl1, dl2, dr1, dr2, lfol, lfor;
int maxdelay;
Stereo<Sample> delaySample;
int dlk, drk, dlhi, dlhi2;
REALTYPE getdelay(REALTYPE xlfo);
REALTYPE dllo, mdel;
};
#endif

View File

@@ -1,481 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Distorsion.cpp - 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(const Stereo<float *> &smp)
{
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] = smp.l[i] * inputvol * panning;
efxoutr[i] = smp.r[i] * inputvol * (1.0 - panning);
}
}
else {
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
efxoutl[i] =
(smp.l[i] * panning + smp.r[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(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(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = (Ppanning + 0.5) / 127.0;
}
void Distorsion::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0 * 1.0;
}
void Distorsion::setlpf(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(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(int npar, 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(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
}

View File

@@ -1,75 +0,0 @@
/*
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
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 DISTORSION_H
#define DISTORSION_H
#include "../globals.h"
#include "../DSP/AnalogFilter.h"
#include "Effect.h"
//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(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
void changepar(int npar, unsigned char value);
unsigned char getpar(int npar) const;
void cleanup();
void applyfilters(REALTYPE *efxoutl, REALTYPE *efxoutr);
private:
//Parametrii
unsigned char Pvolume; //Volume or E/R
unsigned char Ppanning; //Panning
unsigned char Plrcross; // L/R Mixing
unsigned char Pdrive; //the input amplification
unsigned char Plevel; //the output amplification
unsigned char Ptype; //Distorsion type
unsigned char Pnegate; //if the input is negated
unsigned char Plpf; //lowpass filter
unsigned char Phpf; //highpass filter
unsigned char Pstereo; //0=mono,1=stereo
unsigned char Pprefiltering; //if you want to do the filtering before the distorsion
void setvolume(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setlrcross(unsigned char Plrcross);
void setlpf(unsigned char Plpf);
void sethpf(unsigned char Phpf);
//Real Parameters
REALTYPE panning, lrcross;
AnalogFilter *lpfl, *lpfr, *hpfl, *hpfr;
};
#endif

View File

@@ -1,352 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
DynamicFilter.cpp - "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(const Stereo<float *> &smp)
{
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] = smp.l[i];
efxoutr[i] = smp.r[i];
REALTYPE x = (fabs(smp.l[i]) + fabs(smp.l[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(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = pow((Pdepth / 127.0), 2.0);
}
void DynamicFilter::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void DynamicFilter::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
void DynamicFilter::setampsns(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(int npar, 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(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;
}
}

View File

@@ -1,72 +0,0 @@
/*
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
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 DYNAMICFILTER_H
#define DYNAMICFILTER_H
#include "../globals.h"
#include "Effect.h"
#include "EffectLFO.h"
#include "../DSP/Filter.h"
/**DynamicFilter Effect*/
class DynamicFilter:public Effect
{
public:
DynamicFilter(int insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~DynamicFilter();
void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
void changepar(int npar, unsigned char value);
unsigned char getpar(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(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setdepth(unsigned char Pdepth);
void setampsns(unsigned char Pampsns);
void reinitfilter();
//Internal Values
REALTYPE panning, depth, ampsns, ampsmooth;
Filter *filterl, *filterr;
REALTYPE ms1, ms2, ms3, ms4; //mean squares
};
#endif

View File

@@ -1,212 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
EQ.cpp - 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()
{}
void EQ::cleanup()
{
for(int i = 0; i < MAX_EQ_BANDS; i++) {
filter[i].l->cleanup();
filter[i].r->cleanup();
}
}
void EQ::out(const Stereo<float *> &smp)
{
int i;
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] = smp.l[i] * volume;
efxoutr[i] = smp.r[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(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(int npar, 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(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);
}

View File

@@ -1,58 +0,0 @@
/*
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
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 EQ_H
#define EQ_H
#include "../globals.h"
#include "../DSP/AnalogFilter.h"
#include "Effect.h"
/**EQ Effect*/
class EQ:public Effect
{
public:
EQ(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~EQ();
void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
void changepar(int npar, unsigned char value);
unsigned char getpar(int npar) const;
void cleanup();
REALTYPE getfreqresponse(REALTYPE freq);
private:
//Parameters
unsigned char Pvolume; /**<Volume*/
void setvolume(unsigned char Pvolume);
struct {
//parameters
unsigned char Ptype, Pfreq, Pgain, Pq, Pstages;
//internal values
AnalogFilter *l, *r;
} filter[MAX_EQ_BANDS];
};
#endif

View File

@@ -1,270 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Echo.cpp - Echo effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Copyright (C) 2009-2010 Mark McCurry
Author: Nasca Octavian Paul
Mark McCurry
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License
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"
#define MAX_DELAY 2
Echo::Echo(const int &insertion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
samplerate(SAMPLE_RATE),
Pvolume(50), Ppanning(64), Pdelay(60),
Plrdelay(100), Plrcross(100), Pfb(40), Phidamp(60),
delayTime(1), lrdelay(0), avgDelay(0),
delay(new REALTYPE[(int)(MAX_DELAY * samplerate)],
new REALTYPE[(int)(MAX_DELAY * samplerate)]),
old(0.0), pos(0), delta(1), ndelta(1)
{
initdelays();
setpreset(Ppreset);
}
Echo::~Echo()
{
delete[] delay.l;
delete[] delay.r;
}
/*
* Cleanup the effect
*/
void Echo::cleanup()
{
memset(delay.l,0,MAX_DELAY*samplerate*sizeof(REALTYPE));
memset(delay.r,0,MAX_DELAY*samplerate*sizeof(REALTYPE));
old = Stereo<REALTYPE>(0.0);
}
inline int max(int a, int b)
{
return a > b ? a : b;
}
/*
* Initialize the delays
*/
void Echo::initdelays()
{
cleanup();
//number of seconds to delay left chan
float dl = avgDelay - lrdelay;
//number of seconds to delay right chan
float dr = avgDelay + lrdelay;
ndelta.l = max(1,(int) (dl * samplerate));
ndelta.r = max(1,(int) (dr * samplerate));
}
void Echo::out(const Stereo<float *> &input)
{
REALTYPE ldl, rdl;
for(int i = 0; i < SOUND_BUFFER_SIZE; ++i) {
ldl = delay.l[pos.l];
rdl = delay.r[pos.r];
ldl = ldl * (1.0 - lrcross) + rdl * lrcross;
rdl = rdl * (1.0 - lrcross) + ldl * lrcross;
efxoutl[i] = ldl * 2.0;
efxoutr[i] = rdl * 2.0;
ldl = input.l[i] * panning - ldl * fb;
rdl = input.r[i] * (1.0 - panning) - rdl * fb;
//LowPass Filter
old.l = delay.l[(pos.l+delta.l)%(MAX_DELAY * samplerate)] = ldl * hidamp + old.l * (1.0 - hidamp);
old.r = delay.r[(pos.r+delta.r)%(MAX_DELAY * samplerate)] = rdl * hidamp + old.r * (1.0 - hidamp);
//increment
++pos.l;// += delta.l;
++pos.r;// += delta.r;
//ensure that pos is still in bounds
pos.l %= MAX_DELAY * samplerate;
pos.r %= MAX_DELAY * samplerate;
//adjust delay if needed
delta.l = (15*delta.l + ndelta.l)/16;
delta.r = (15*delta.r + ndelta.r)/16;
}
}
/*
* Parameter control
*/
void Echo::setvolume(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(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = (Ppanning + 0.5) / 127.0;
}
void Echo::setdelay(unsigned char Pdelay)
{
this->Pdelay=Pdelay;
avgDelay=(Pdelay/127.0*1.5);//0 .. 1.5 sec
initdelays();
}
void Echo::setlrdelay(unsigned char Plrdelay)
{
REALTYPE tmp;
this->Plrdelay = Plrdelay;
tmp =
(pow(2, fabs(Plrdelay - 64.0) / 64.0 * 9) - 1.0) / 1000.0;
if(Plrdelay < 64.0)
tmp = -tmp;
lrdelay = tmp;
initdelays();
}
void Echo::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0 * 1.0;
}
void Echo::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
fb = Pfb / 128.0;
}
void Echo::sethidamp(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(int npar, 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(int npar) const
{
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
}

View File

@@ -1,140 +0,0 @@
/*
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
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 ECHO_H
#define ECHO_H
#include "../globals.h"
#include "Effect.h"
#include "../Misc/Stereo.h"
#include "../Samples/Sample.h"
/**Echo Effect*/
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 destructor
*/
~Echo();
void out(const Stereo<float *> &input);
/**
* Sets the state of Echo to the specified preset
* @param npreset number of chosen preset
*/
void setpreset(unsigned char npreset);
/**
* 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(int npar, unsigned char value);
/**
* 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(int npar) const;
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:
int samplerate;
//Parameters
char Pvolume; /**<#1 Volume or Dry/Wetness*/
char Ppanning; /**<#2 Panning*/
char Pdelay; /**<#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(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setdelay(unsigned char Pdelay);
void setlrdelay(unsigned char Plrdelay);
void setlrcross(unsigned char Plrcross);
void setfb(unsigned char Pfb);
void sethidamp(unsigned char Phidamp);
//Real Parameters
REALTYPE panning, lrcross, fb, hidamp;
//Left/Right delay lengths
Stereo<int> delayTime;
REALTYPE lrdelay;
REALTYPE avgDelay;
void initdelays();
//2 channel ring buffer
Stereo<REALTYPE *> delay;
Stereo<REALTYPE> old;
//position of reading/writing from delaysample
Stereo<int> pos;
//step size for delay buffer
Stereo<int> delta;
Stereo<int> ndelta;
};
#endif

View File

@@ -1,36 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Effect.cpp - 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
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 "Effect.h"
Effect::Effect(bool insertion_, REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_, FilterParams *filterpars_,
const unsigned char &Ppreset_)
:Ppreset(Ppreset_), efxoutl(efxoutl_), efxoutr(efxoutr_),
filterpars(filterpars_), insertion(insertion_)
{}
void Effect::out(REALTYPE *const smpsl, REALTYPE *const smpsr)
{
out(Stereo<float *>(smpsl,smpsr));
};

View File

@@ -1,105 +0,0 @@
/*
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
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 EFFECT_H
#define EFFECT_H
#include "../Misc/Util.h"
#include "../globals.h"
#include "../Params/FilterParams.h"
#include "../Misc/Stereo.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(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(int npar, unsigned char value) = 0;
/**Get the value of parameter npar
* @param npar chosen parameter
* @return the value of the parameter in an unsigned char or 0 if it
* does not exist*/
virtual unsigned char getpar(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
*/
void out(REALTYPE *const smpsl, REALTYPE *const smpsr);
virtual void out(const Stereo<float *> &smp) = 0;
/**Reset the state of the effect*/
virtual void cleanup() {}
/**This is only used for EQ (for user interface)*/
virtual REALTYPE getfreqresponse(REALTYPE freq) {
return freq;
}
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 Stereo<float*>*/
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;
FilterParams *filterpars; /**<Parameters for filters used by Effect*/
protected:
const bool insertion;/**<If Effect is an insertion effect, insertion=1
*otherwise, it should be insertion=0*/
};
#endif

View File

@@ -1,127 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
EffectLFO.cpp - 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
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 <cstdlib>
#include <cmath>
#include "EffectLFO.h"
EffectLFO::EffectLFO()
{
xl = 0.0;
xr = 0.0;
Pfreq = 40;
Prandomness = 0;
PLFOtype = 0;
Pstereo = 96;
updateparams();
ampl1 = (1 - lfornd) + lfornd * RND;
ampl2 = (1 - lfornd) + lfornd * RND;
ampr1 = (1 - lfornd) + lfornd * RND;
ampr2 = (1 - lfornd) + lfornd * RND;
}
EffectLFO::~EffectLFO()
{}
/*
* Update the changed parameters
*/
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(PLFOtype > 1)
PLFOtype = 1; //this has to be updated if more lfo's are added
lfotype = PLFOtype;
xr = fmod(xl + (Pstereo - 64.0) / 127.0 + 1.0, 1.0);
}
/*
* Compute the shape of the LFO
*/
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
}
return out;
}
/*
* LFO output
*/
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;
}
*outl = (out + 1.0) * 0.5;
out = getlfoshape(xr);
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;
}
*outr = (out + 1.0) * 0.5;
}

View File

@@ -1,53 +0,0 @@
/*
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
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 EFFECT_LFO_H
#define EFFECT_LFO_H
#include "../globals.h"
/**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);
void updateparams();
unsigned char Pfreq;
unsigned char Prandomness;
unsigned char PLFOtype;
unsigned char Pstereo; //"64"=0
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 (replace with short or enum)*/
};
#endif

View File

@@ -1,357 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
EffectMgr.cpp - 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"
#include <iostream>
using namespace std;
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();
}

View File

@@ -1,102 +0,0 @@
/*
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
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 EFFECTMGR_H
#define EFFECTMGR_H
#include <pthread.h>
#include "Effect.h"
#include "Reverb.h"
#include "Echo.h"
#include "Chorus.h"
#include "Phaser.h"
#include "Alienwah.h"
#include "Distorsion.h"
#include "EQ.h"
#include "DynamicFilter.h"
#include "../Misc/XMLwrapper.h"
#include "../Params/FilterParams.h"
#include "../Params/Presets.h"
/**Effect manager, an interface betwen the program and effects*/
class EffectMgr:public Presets
{
public:
EffectMgr(int insertion_, pthread_mutex_t *mutex_);
~EffectMgr();
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
void out(REALTYPE *smpsl, REALTYPE *smpsr);
void setdryonly(bool value);
/**get the output(to speakers) volume of the systemeffect*/
REALTYPE sysefxgetvolume();
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*/
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
* \todo needs to be decoupled*/
REALTYPE getEQfreqresponse(REALTYPE freq);
FilterParams *filterpars;
private:
int nefx;
Effect *efx;
pthread_mutex_t *mutex;
bool dryonly;
};
#endif

View File

@@ -1,473 +0,0 @@
/*
Phaser.cpp - Phasing and Approximate digital model of an analog JFET phaser.
Analog modeling implemented by Ryan Billing aka Transmogrifox.
ZynAddSubFX - a software synthesizer
Phaser.cpp - Phaser effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Copyright (C) 2009-2010 Ryan Billing
Copyright (C) 2010-2010 Mark McCurry
Author: Nasca Octavian Paul
Ryan Billing
Mark McCurry
DSP analog modeling theory & practice largely influenced by various CCRMA publications, particularly works by Julius O. Smith.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (version 2 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 <algorithm>
#include "Phaser.h"
using namespace std;
#define PHASER_LFO_SHAPE 2
#define ONE_ 0.99999f // To prevent LFO ever reaching 1.0 for filter stability purposes
#define ZERO_ 0.00001f // Same idea as above.
Phaser::Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(NULL), xn1(NULL), yn1(NULL), diff(0.0), oldgain(0.0),
fb(0.0)
{
analog_setup();
setpreset(Ppreset);
cleanup();
}
void Phaser::analog_setup()
{
//model mismatch between JFET devices
offset[0] = -0.2509303f;
offset[1] = 0.9408924f;
offset[2] = 0.998f;
offset[3] = -0.3486182f;
offset[4] = -0.2762545f;
offset[5] = -0.5215785f;
offset[6] = 0.2509303f;
offset[7] = -0.9408924f;
offset[8] = -0.998f;
offset[9] = 0.3486182f;
offset[10] = 0.2762545f;
offset[11] = 0.5215785f;
barber = 0; //Deactivate barber pole phasing by default
mis = 1.0f;
Rmin = 625.0f;// 2N5457 typical on resistance at Vgs = 0
Rmax = 22000.0f;// Resistor parallel to FET
Rmx = Rmin/Rmax;
Rconst = 1.0f + Rmx; // Handle parallel resistor relationship
C = 0.00000005f; // 50 nF
CFs = (float) 2.0f*(float)SAMPLE_RATE*C;
invperiod = 1.0f / ((float) SOUND_BUFFER_SIZE);
}
Phaser::~Phaser()
{
if(xn1.l)
delete[] xn1.l;
if(yn1.l)
delete[] yn1.l;
if(xn1.r)
delete[] xn1.r;
if(yn1.r)
delete[] yn1.r;
}
/*
* Effect output
*/
void Phaser::out(const Stereo<REALTYPE *> &input)
{
if(Panalog)
AnalogPhase(input);
else
normalPhase(input);
}
void Phaser::AnalogPhase(const Stereo<REALTYPE *> &input)
{
Stereo<REALTYPE> gain(0.0), lfoVal(0.0), mod(0.0), g(0.0), b(0.0), hpf(0.0);
lfo.effectlfoout(&lfoVal.l, &lfoVal.r);
mod.l = lfoVal.l*width + (depth - 0.5f);
mod.r = lfoVal.r*width + (depth - 0.5f);
mod.l = limit(mod.l, ZERO_, ONE_);
mod.r = limit(mod.r, ZERO_, ONE_);
if(Phyper) {
//Triangle wave squared is approximately sin on bottom, tri on top
//Result is exponential sweep more akin to filter in synth with
//exponential generator circuitry.
mod.l *= mod.l;
mod.r *= mod.r;
}
//g.l,g.r is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)]
mod.l = sqrtf(1.0f - mod.l);
mod.r = sqrtf(1.0f - mod.r);
diff.r = (mod.r - oldgain.r) * invperiod;
diff.l = (mod.l - oldgain.l) * invperiod;
g = oldgain;
oldgain = mod;
for (int i = 0; i < SOUND_BUFFER_SIZE; i++) {
g.l += diff.l;// Linear interpolation between LFO samples
g.r += diff.r;
Stereo<REALTYPE> xn(input.l[i] * panning,
input.r[i] * (1.0f - panning));
if (barber) {
g.l = fmodf((g.l + 0.25f), ONE_);
g.r = fmodf((g.r + 0.25f), ONE_);
}
xn.l = applyPhase(xn.l, g.l, fb.l, hpf.l, yn1.l, xn1.l);
xn.r = applyPhase(xn.r, g.r, fb.r, hpf.r, yn1.r, xn1.r);
fb.l = xn.l * feedback;
fb.r = xn.r * feedback;
efxoutl[i] = xn.l;
efxoutr[i] = xn.r;
}
if(Poutsub) {
invSignal(efxoutl, SOUND_BUFFER_SIZE);
invSignal(efxoutr, SOUND_BUFFER_SIZE);
}
}
REALTYPE Phaser::applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb,
REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1)
{
for(int j = 0; j < Pstages; j++) { //Phasing routine
mis = 1.0f + offsetpct*offset[j];
//This is symmetrical.
//FET is not, so this deviates slightly, however sym dist. is
//better sounding than a real FET.
float d = (1.0f + 2.0f*(0.25f + g)*hpf*hpf*distortion) * mis;
Rconst = 1.0f + mis*Rmx;
// This is 1/R. R is being modulated to control filter fc.
float b = (Rconst - g)/ (d*Rmin);
float gain = (CFs - b)/(CFs + b);
yn1[j] = gain * (x + yn1[j]) - xn1[j];
//high pass filter:
//Distortion depends on the high-pass part of the AP stage.
hpf = yn1[j] + (1.0f-gain)*xn1[j];
xn1[j] = x;
x = yn1[j];
if (j==1)
x += fb; //Insert feedback after first phase stage
}
return x;
}
void Phaser::normalPhase(const Stereo<REALTYPE *> &input)
{
Stereo<REALTYPE> gain(0.0), lfoVal(0.0);
lfo.effectlfoout(&lfoVal.l, &lfoVal.r);
gain.l = (exp(lfoVal.l * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0);
gain.r = (exp(lfoVal.r * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0);
gain.l = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * gain.l * depth;
gain.r = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * gain.r * depth;
gain.l = limit(gain.l, ZERO_, ONE_);
gain.r = limit(gain.r, ZERO_, ONE_);
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
REALTYPE x = (REALTYPE) i / SOUND_BUFFER_SIZE;
REALTYPE x1 = 1.0 - x;
//TODO think about making panning an external feature
Stereo<REALTYPE> xn(input.l[i] * panning + fb.l,
input.r[i] * (1.0 - panning) + fb.r);
Stereo<REALTYPE> g(gain.l * x + oldgain.l * x1,
gain.r * x + oldgain.r * x1);
xn.l = applyPhase(xn.l, g.l, old.l);
xn.r = applyPhase(xn.r, g.r, old.r);
//Left/Right crossing
crossover(xn.l, xn.r, lrcross);
fb.l = xn.l * feedback;
fb.r = xn.r * feedback;
efxoutl[i] = xn.l;
efxoutr[i] = xn.r;
}
oldgain = gain;
if(Poutsub) {
invSignal(efxoutl, SOUND_BUFFER_SIZE);
invSignal(efxoutr, SOUND_BUFFER_SIZE);
}
}
REALTYPE Phaser::applyPhase(REALTYPE x, REALTYPE g, REALTYPE *old)
{
for(int j = 0; j < Pstages * 2; j++) { //Phasing routine
REALTYPE tmp = old[j];
old[j] = g * tmp + x;
x = tmp - g *old[j];
}
return x;
}
/*
* Cleanup the effect
*/
void Phaser::cleanup()
{
fb = oldgain = Stereo<REALTYPE>(0.0);
for(int i = 0; i < Pstages * 2; i++) {
old.l[i] = 0.0;
old.r[i] = 0.0;
}
for(int i = 0; i < Pstages; i++) {
xn1.l[i] = 0.0;
yn1.l[i] = 0.0;
xn1.r[i] = 0.0;
yn1.r[i] = 0.0;
}
}
/*
* Parameter control
*/
void Phaser::setwidth(unsigned char Pwidth)
{
this->Pwidth = Pwidth;
width = ((float)Pwidth / 127.0f);
}
void Phaser::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
feedback = (float) (Pfb - 64) / 64.2f;
}
void Phaser::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void Phaser::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = (float)Ppanning / 127.0;
}
void Phaser::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
}
void Phaser::setdistortion(unsigned char Pdistortion)
{
this->Pdistortion = Pdistortion;
distortion = (float)Pdistortion / 127.0f;
}
void Phaser::setoffset(unsigned char Poffset)
{
this->Poffset = Poffset;
offsetpct = (float)Poffset / 127.0f;
}
void Phaser::setstages(unsigned char Pstages)
{
if(xn1.l)
delete[] xn1.l;
if(yn1.l)
delete[] yn1.l;
if(xn1.r)
delete[] xn1.r;
if(yn1.r)
delete[] yn1.r;
this->Pstages = min(MAX_PHASER_STAGES, (int)Pstages);
old = Stereo<REALTYPE *>(new REALTYPE[Pstages * 2],
new REALTYPE[Pstages * 2]);
xn1 = Stereo<REALTYPE *>(new REALTYPE[Pstages],
new REALTYPE[Pstages]);
yn1 = Stereo<REALTYPE *>(new REALTYPE[Pstages],
new REALTYPE[Pstages]);
cleanup();
}
void Phaser::setphase(unsigned char Pphase)
{
this->Pphase = Pphase;
phase = (Pphase / 127.0);
}
void Phaser::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = (float)(Pdepth) / 127.0f;
}
void Phaser::setpreset(unsigned char npreset)
{
const int PRESET_SIZE = 15;
const int NUM_PRESETS = 12;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//Phaser
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
{64, 64, 36, 0, 0, 64, 110, 64, 1, 0, 0, 20, 0, 0, 0},
{64, 64, 35, 0, 0, 88, 40, 64, 3, 0, 0, 20, 0, 0, 0},
{64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20, 0, 0, 0},
{39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20, 0, 0, 0},
{64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20, 0, 0, 0},
{64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20, 0, 0, 0},
//APhaser
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
{64, 64, 14, 0, 1, 64, 64, 40, 4, 10, 0, 110, 1, 20, 1},
{64, 64, 14, 5, 1, 64, 70, 40, 6, 10, 0, 110, 1, 20, 1},
{64, 64, 9, 0, 0, 64, 60, 40, 8, 10, 0, 40, 0, 20, 1},
{64, 64, 14, 10, 0, 64, 45, 80, 7, 10, 1, 110, 1, 20, 1},
{25, 64, 127, 10, 0, 64, 25, 16, 8, 100, 0, 25, 0, 20, 1},
{64, 64, 1, 10, 1, 64, 70, 40, 12, 10, 0, 110, 1, 20, 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 Phaser::changepar(int npar, 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();
barber = (2 == value);
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);
setoffset(value);
break;
case 10:
Poutsub = min((int)value,1);
break;
case 11:
setphase(value);
setwidth(value);
break;
case 12:
Phyper = min((int)value, 1);
break;
case 13:
setdistortion(value);
break;
case 14:
Panalog = value;
break;
}
}
unsigned char Phaser::getpar(int npar) const
{
switch(npar) {
case 0:
return Pvolume;
case 1:
return Ppanning;
case 2:
return lfo.Pfreq;
case 3:
return lfo.Prandomness;
case 4:
return lfo.PLFOtype;
case 5:
return lfo.Pstereo;
case 6:
return Pdepth;
case 7:
return Pfb;
case 8:
return Pstages;
case 9:
return Plrcross;
return Poffset;
case 10:
return Poutsub;
case 11:
return Pphase;
return Pwidth;
case 12:
return Phyper;
case 13:
return Pdistortion;
case 14:
return Panalog;
default:
return 0;
}
}

View File

@@ -1,103 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Phaser.h - Phaser effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Copyright (C) 2009-2010 Ryan Billing
Copyright (C) 2010-2010 Mark McCurry
Author: Nasca Octavian Paul
Ryan Billing
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 PHASER_H
#define PHASER_H
#include "../globals.h"
#include "Effect.h"
#include "EffectLFO.h"
#define MAX_PHASER_STAGES 12
class Phaser:public Effect
{
public:
Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~Phaser();
void out(const Stereo<REALTYPE *> &input);
void setpreset(unsigned char npreset);
void changepar(int npar, unsigned char value);
unsigned char getpar(int npar) const;
void cleanup();
private:
//Phaser parameters
EffectLFO lfo; //Phaser modulator
unsigned char Pvolume; //Used to set wet/dry mix
unsigned char Ppanning;
unsigned char Pdistortion; //Model distortion added by FET element
unsigned char Pdepth; //Depth of phaser sweep
unsigned char Pwidth; //Phaser width (LFO amplitude)
unsigned char Pfb; //feedback
unsigned char Poffset; //Model mismatch between variable resistors
unsigned char Plrcross; //crossover
unsigned char Pstages; //Number of first-order All-Pass stages
unsigned char Poutsub; //if I wish to subtract the output instead of adding
unsigned char Pphase;
unsigned char Phyper; //lfo^2 -- converts tri into hyper-sine
unsigned char Panalog;
//Control parameters
void setvolume(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setdepth(unsigned char Pdepth);
void setfb(unsigned char Pfb);
void setdistortion(unsigned char Pdistortion);
void setwidth(unsigned char Pwidth);
void setoffset(unsigned char Poffset);
void setlrcross(unsigned char Plrcross);
void setstages(unsigned char Pstages);
void setphase(unsigned char Pphase);
//Internal Variables
bool barber; //Barber pole phasing flag
REALTYPE distortion, width, offsetpct;
REALTYPE panning, feedback, depth, lrcross, phase;
Stereo<REALTYPE *> old, xn1, yn1;
Stereo<REALTYPE> diff, oldgain, fb;
REALTYPE invperiod;
REALTYPE offset[12];
float mis;
float Rmin; // 3N5457 typical on resistance at Vgs = 0
float Rmax; // Resistor parallel to FET
float Rmx; // Rmin/Rmax to avoid division in loop
float Rconst; // Handle parallel resistor relationship
float C; // Capacitor
float CFs; // A constant derived from capacitor and resistor relationships
void analog_setup();
void AnalogPhase(const Stereo<REALTYPE *> &input);
//analog case
REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb,
REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1);
void normalPhase(const Stereo<REALTYPE *> &input);
REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE *old);
};
#endif

View File

@@ -1,551 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Reverb.cpp - 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];
bandwidth = NULL;
//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;
Pbandwidth = 30;
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;
if(bandwidth)
delete bandwidth;
}
/*
* 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(const Stereo<float *> &smp)
{
int i;
if((Pvolume == 0) && (insertion != 0))
return;
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0;
if(idelay != NULL) {
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
//Initial delay r
REALTYPE tmp = inputbuf[i] + idelay[idelayk] * idelayfb;
inputbuf[i] = idelay[idelayk];
idelay[idelayk] = tmp;
idelayk++;
if(idelayk >= idelaylen)
idelayk = 0;
}
}
if(bandwidth)
bandwidth->process(SOUND_BUFFER_SIZE, inputbuf);
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(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(unsigned char Ppan)
{
this->Ppan = Ppan;
pan = (REALTYPE)Ppan / 127.0;
}
void Reverb::settime(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)
{
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;
REALTYPE x = fabs((REALTYPE)(Plohidamp - 64) / 64.1);
lohifb = x * x;
}
}
void Reverb::setidelay(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(unsigned char Pidelayfb)
{
this->Pidelayfb = Pidelayfb;
idelayfb = Pidelayfb / 128.0;
}
void Reverb::sethpf(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(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 = 3;
const 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 },
//Freeverb by Jezar at Dreampoint //duplicate
{1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 }
};
const int aptunings[NUM_TYPES][REV_APS] = {
//this is unused (for random)
{0, 0, 0, 0 },
//Freeverb by Jezar at Dreampoint
{225, 341, 441, 556 },
//Freeverb by Jezar at Dreampoint (duplicate)
{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();
if(bandwidth)
delete bandwidth;
bandwidth = NULL;
if(Ptype == 2) { //bandwidth
bandwidth = new Unison(SOUND_BUFFER_SIZE / 4 + 1, 2.0);
bandwidth->set_size(50);
bandwidth->set_base_frequency(1.0);
}
}
void Reverb::setroomsize(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::setbandwidth(unsigned char Pbandwidth) {
this->Pbandwidth = Pbandwidth;
REALTYPE v = Pbandwidth / 127.0;
if(bandwidth)
bandwidth->set_bandwidth(pow(v, 2.0) * 200.0);
}
void Reverb::setpreset(unsigned char npreset)
{
const int PRESET_SIZE = 13;
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, 20 },
//Cathedral2
{80, 64, 69, 35, 0, 0, 0, 127, 0, 71, 0, 64, 20 },
//Cathedral3
{80, 64, 69, 24, 0, 0, 0, 127, 75, 78, 1, 85, 20 },
//Hall1
{90, 64, 51, 10, 0, 0, 0, 127, 21, 78, 1, 64, 20 },
//Hall2
{90, 64, 53, 20, 0, 0, 0, 127, 75, 71, 1, 64, 20 },
//Room1
{100, 64, 33, 0, 0, 0, 0, 127, 0, 106, 0, 30, 20 },
//Room2
{100, 64, 21, 26, 0, 0, 0, 62, 0, 77, 1, 45, 20 },
//Basement
{110, 64, 14, 0, 0, 0, 0, 127, 5, 71, 0, 25, 20 },
//Tunnel
{85, 80, 84, 20, 42, 0, 0, 51, 0, 78, 1, 105, 20 },
//Echoed1
{95, 64, 26, 60, 71, 0, 0, 114, 0, 64, 1, 64, 20 },
//Echoed2
{90, 64, 40, 88, 71, 0, 0, 114, 0, 88, 1, 64, 20 },
//VeryLong1
{90, 64, 93, 15, 0, 0, 0, 114, 0, 77, 0, 95, 20 },
//VeryLong2
{90, 64, 111, 30, 0, 0, 0, 114, 90, 74, 1, 80, 20 }
};
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(int npar, 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;
case 12:
setbandwidth(value);
break;
}
}
unsigned char Reverb::getpar(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;
case 12:
return Pbandwidth;
break;
}
return 0; //in case of bogus "parameter"
}

View File

@@ -1,135 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Reverb.h - Reverberation effect
Copyright (C) 2002-2009 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 <math.h>
#include "../globals.h"
#include "../DSP/AnalogFilter.h"
#include "../DSP/FFTwrapper.h"
#include "../DSP/Unison.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(const Stereo<float *> &smp);
void cleanup();
void setpreset(unsigned char npreset);
void changepar(int npar, unsigned char value);
unsigned char getpar(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;
/**Bandwidth */
unsigned char Pbandwidth;
//parameter control
void setvolume(unsigned char Pvolume);
void setpan(unsigned char Ppan);
void settime(unsigned char Ptime);
void setlohidamp(unsigned char Plohidamp);
void setidelay(unsigned char Pidelay);
void setidelayfb(unsigned char Pidelayfb);
void sethpf(unsigned char Phpf);
void setlpf(unsigned char Plpf);
void settype(unsigned char Ptype);
void setroomsize(unsigned char Proomsize);
void setbandwidth(unsigned char Pbandwidth);
REALTYPE pan, erbalance;
//Parameters
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];
Unison *bandwidth;
//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

View File

@@ -1,118 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
ALSAMidiIn.cpp - 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;
}

View File

@@ -1,51 +0,0 @@
/*
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
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 ALSA_MIDI_IN_H
#define ALSA_MIDI_IN_H
#include <alsa/asoundlib.h>
#include "MidiIn.h"
/**Midi input for ALSA (this creates an ALSA virtual port)*/
class ALSAMidiIn:public MidiIn
{
public:
/**Constructor*/
ALSAMidiIn();
/**Destructor*/
~ALSAMidiIn();
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

View File

@@ -1,19 +0,0 @@
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}
)

View File

@@ -1,96 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
MidiIn.cpp - 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;
}

View File

@@ -1,52 +0,0 @@
/*
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
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 MIDI_IN_H
#define MIDI_IN_H
#include "../globals.h"
enum MidiCmdType {
MidiNull, MidiNoteOFF, MidiNoteON, MidiController
};
#define MP_MAX_BYTES 4000 //in case of loooong SYS_EXes
/**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

View File

@@ -1,41 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
NULLMidiIn.cpp - 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
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 "NULLMidiIn.h"
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,
int *cmdparams)
{
cmdtype = MidiNull;
}

View File

@@ -1,50 +0,0 @@
/*
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
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 NULL_MIDI_IN_H
#define NULL_MIDI_IN_H
#include "MidiIn.h"
/**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:
};
#endif

View File

@@ -1,123 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
OSSMidiIn.cpp - 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
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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/soundcard.h>
#include "OSSMidiIn.h"
#include "../Misc/Util.h"
OSSMidiIn::OSSMidiIn()
{
inputok = false;
midi_handle = open(config.cfg.LinuxOSSSeqInDev, O_RDONLY, 0);
if(midi_handle != -1)
inputok = true;
lastmidicmd = 0;
cmdtype = 0;
cmdchan = 0;
}
OSSMidiIn::~OSSMidiIn()
{
close(midi_handle);
}
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);
}
return tmp[1];
}
unsigned char OSSMidiIn::getmidibyte()
{
unsigned char b;
do {
b = readbyte();
} while(b == 0xfe); //drops the Active Sense Messages
return b;
}
/*
* Get the midi command,channel and parameters
*/
void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams)
{
unsigned char tmp, i;
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;
}
tmp = getmidibyte();
if(tmp >= 0x80) {
lastmidicmd = tmp;
tmp = getmidibyte();
}
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
}
}

View File

@@ -1,50 +0,0 @@
/*
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
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 OSS_MIDI_IN_H
#define OSS_MIDI_IN_H
#include "MidiIn.h"
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
private:
int midi_handle;
unsigned char lastmidicmd; //last byte (>=80) received from the Midi
};
#endif

View File

@@ -1,94 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
WINMidiIn.cpp - 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);
}

View File

@@ -1,34 +0,0 @@
/*
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
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 WIN_MIDI_IN_H
#define WIN_MIDI_IN_H
#include "../Misc/Master.h"
void InitWinMidi(Master *master_);
void StopWinMidi();
#endif

View File

@@ -1,644 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
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
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 "Bank.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "Config.h"
#define INSTRUMENT_EXTENSION ".xiz"
//if this file exists into a directory, this make the directory to be considered as a bank, even if it not contains a instrument file
#define FORCE_BANK_DIR_FILE ".bankdir"
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;
}
dirname = NULL;
clearbank();
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;
}
clearbank();
}
/*
* Get the name of an instrument from the bank
*/
char *Bank::getname(unsigned int ninstrument)
{
if(emptyslot(ninstrument))
return defaultinsname;
return ins[ninstrument].name;
}
/*
* Get the numbered name of an instrument from the bank
*/
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];
}
/*
* Changes the name of an instrument (and the filename)
*/
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);
//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] = '_';
}
snprintf(newfilename, 1000, "%s/%s.xiz", dirname, tmpfilename);
// printf("rename %s -> %s\n",ins[ninstrument].filename,newfilename);//////////////
rename(ins[ninstrument].filename, newfilename);
if(ins[ninstrument].filename)
delete [] ins[ninstrument].filename;
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)
{
if(ninstrument >= BANK_SIZE)
return 1;
if(ins[ninstrument].filename == NULL)
return 1;
if(ins[ninstrument].used)
return 0;
else
return 1;
}
/*
* Removes the instrument from the bank
*/
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
*/
void Bank::savetoslot(unsigned int ninstrument, Part *part)
{
clearslot(ninstrument);
const int maxfilename = 200;
char tmpfilename[maxfilename + 20];
ZERO(tmpfilename, maxfilename + 20);
snprintf(tmpfilename,
maxfilename,
"%4d-%s",
ninstrument + 1,
(char *)part->Pname);
//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] = '_';
}
strncat(tmpfilename, ".xiz", maxfilename + 10);
int fnsize = strlen(dirname) + strlen(tmpfilename) + 10;
char *filename = new char[fnsize + 4];
ZERO(filename, fnsize + 2);
snprintf(filename, fnsize, "%s/%s", dirname, tmpfilename);
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)
{
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)
{
DIR *dir = opendir(bankdirname);
clearbank();
if(dir == NULL)
return -1;
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);
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);
;
}
closedir(dir);
if(dirname != NULL)
sprintf(config.cfg.currentBankDir, "%s", dirname);
;
return 0;
}
/*
* Makes a new bank, put it on a file and makes it current bank
*/
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 - strlen(bankdir) - 1 );
;
strncat(bankdir, newbankdirname, MAX_STRING_SIZE - strlen(bankdir) - 1);
#ifdef OS_WINDOWS
result = mkdir(bankdir);
#else
result = mkdir(bankdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
if(result < 0)
return -1;
snprintf(tmpfilename,
MAX_STRING_SIZE,
"%s/%s",
bankdir,
FORCE_BANK_DIR_FILE);
// 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()
{
return dirname == NULL;
}
/*
* Swaps a slot with another
*/
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(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;
}
}
//a helper function that compares 2 banks[] arrays
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;
int result = strcasecmp(bank1->name, bank2->name);
return result < 0;
}
/*
* 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;
}
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;
banks[i].name = banks[j].name;
banks[i].dir = banks[j].dir;
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;
}
}
}
// private stuff
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];
} bank;
const char *separator = "/";
if(strlen(rootdir)) {
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);
}
}
}
closedir(dir);
}
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
}
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;
}
;
}
if(pos < 0)
return -1; //the bank is full
// printf("%s %d\n",filename,pos);
deletefrombank(pos);
ins[pos].used = true;
snprintf(ins[pos].name, PART_MAX_NAME_LEN, "%s", name);
snprintf(tmpinsname[pos], PART_MAX_NAME_LEN + 10, " ");
int len = strlen(filename) + 1 + strlen(dirname);
ins[pos].filename = new char[len + 2];
ins[pos].filename[len + 1] = 0;
snprintf(ins[pos].filename, len + 1, "%s/%s", dirname, filename);
//see if PADsynth is used
if(config.cfg.CheckPADsynth) {
XMLwrapper *xml = new XMLwrapper();
xml->loadXMLfile(ins[pos].filename);
ins[pos].info.PADsynth_used = xml->hasPadSynth();
delete xml;
}
else
ins[pos].info.PADsynth_used = false;
return 0;
}
bool Bank::isPADsynth_used(unsigned int ninstrument)
{
if(config.cfg.CheckPADsynth == 0)
return 0;
else
return ins[ninstrument].info.PADsynth_used;
}
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;
}
ZERO(tmpinsname[pos], PART_MAX_NAME_LEN + 20);
}

View File

@@ -1,108 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
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
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 BANK_H
#define BANK_H
#include "../globals.h"
#include "XMLwrapper.h"
#include "Part.h"
#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);
/**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);
/**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);
/**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;
void scanrootdir(char *rootdir); //scans a root dir for banks
};
#endif

View File

@@ -1,24 +0,0 @@
if(NOT ("${MXML_INCLUDE_DIR}" STREQUAL ""))
include_directories("${MXML_INCLUDE_DIR}")
endif()
set(zynaddsubfx_misc_SRCS
Bank.cpp
Config.cpp
Dump.cpp
Master.cpp
Microtonal.cpp
Part.cpp
Util.cpp
QtXmlWrapper.cpp
)
if (LASH_FOUND)
set(zynaddsubfx_misc_SRCS ${zynaddsubfx_misc_SRCS} LASHClient.cpp)
endif()
add_library(zynaddsubfx_misc STATIC
${zynaddsubfx_misc_SRCS}
)
target_link_libraries(zynaddsubfx_misc zynaddsubfx_output)

View File

@@ -1,409 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Config.cpp - 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() :
workingDir( NULL )
{}
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;
if( workingDir != NULL )
{
snprintf(name, namesize, "%s%s", workingDir, ".zynaddsubfxXML.cfg");
}
else
{
#ifdef OS_LINUX
snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg");
#else
snprintf(name, namesize, "%s", "zynaddsubfxXML.cfg");
#endif
}
}

View File

@@ -1,73 +0,0 @@
/*
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
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 CONFIG_H
#define CONFIG_H
#include "../globals.h"
#define MAX_STRING_SIZE 4000
#define MAX_BANK_ROOT_DIRS 100
/**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;
char * workingDir;
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

View File

@@ -1,100 +0,0 @@
/*
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_ */

View File

@@ -1,124 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Dump.cpp - 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
}

View File

@@ -1,64 +0,0 @@
/*
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
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 DUMP_H
#define DUMP_H
#include <stdio.h>
/**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

View File

@@ -1,104 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
LASHClient.cpp - 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));
}

View File

@@ -1,66 +0,0 @@
/*
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

View File

@@ -1,828 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Master.cpp - 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(&microtonal, 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();
}
}

View File

@@ -1,177 +0,0 @@
/*
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
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 MASTER_H
#define MASTER_H
#include "../globals.h"
#include "../Effects/EffectMgr.h"
#include "Part.h"
#include "../Output/Recorder.h"
#include "Microtonal.h"
#include "Bank.h"
#include "Dump.h"
#include "../Seq/Sequencer.h"
#include "XMLwrapper.h"
extern Dump dump;
/** 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
* @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);
void defaults();
/**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)
* @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);
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;
//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
Controller ctl;
int swaplr; //1 if L and R are swapped
//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;
//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
//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);
};
#endif

View File

@@ -1,687 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Microtonal.cpp - 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 &micro) const
{
return !(*this != micro);
}
bool Microtonal::operator!=(const Microtonal &micro) 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.%06d", 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;
}

View File

@@ -1,135 +0,0 @@
/*
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
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 MICROTONAL_H
#define MICROTONAL_H
#include "../globals.h"
#include "XMLwrapper.h"
#define MAX_OCTAVE_SIZE 128
#define MICROTONAL_MAX_NAME_LEN 120
#include <stdio.h>
/**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;
//Parameters
/**if the keys are inversed (the pitch is lower to keys from the right direction)*/
unsigned char Pinvertupdown;
/**the central key of the inversion*/
unsigned char Pinvertupdowncenter;
/**0 for 12 key temperate scale, 1 for microtonal*/
unsigned char Penabled;
/**the note of "A" key*/
unsigned char PAnote;
/**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;
//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 &micro) const;
bool operator!=(const Microtonal &micro) 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];
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,206 +0,0 @@
/*
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
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 PART_H
#define PART_H
#define MAX_INFO_TEXT_SIZE 1000
#include "../globals.h"
#include "../Params/ADnoteParameters.h"
#include "../Params/SUBnoteParameters.h"
#include "../Params/PADnoteParameters.h"
#include "../Synth/ADnote.h"
#include "../Synth/SUBnote.h"
#include "../Synth/PADnote.h"
#include "../Params/Controller.h"
#include "../Misc/Microtonal.h"
#include "../DSP/FFTwrapper.h"
#include "../Effects/EffectMgr.h"
#include "XMLwrapper.h"
#include <list> // For the monomemnotes list.
/** Part implementation*/
class 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
/* 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);
void add2XML(XMLwrapper *xml);
void add2XMLinstrument(XMLwrapper *xml);
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 {
unsigned char Penabled, Pmuted, Pminkey, Pmaxkey;
unsigned char *Pname;
unsigned char Padenabled, Psubenabled, Ppadenabled;
unsigned char Psendtoparteffect;
ADnoteParameters *adpars;
SUBnoteParameters *subpars;
PADnoteParameters *padpars;
} 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)
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
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
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 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[] is used in conjunction with the list to
store the velocity and masterkeyshift values of a
given note (the list only store note values).
For example 'monomem[note].velocity' would be the
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;
};
#endif

View File

@@ -1,550 +0,0 @@
/*
* QtXmlWrapper.cpp - a QtXml based XML backend for ZynAddSubxFX
*
* Copyright (c) 2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
/* File derived from QtXmlWrapper.C: */
/*
ZynAddSubFX - a software synthesizer
QtXmlWrapper.C - 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
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 <QtXml/QDomDocument>
#include <QtCore/QDebug>
#include "QtXmlWrapper.h"
#include <string>
#include <sstream>
#include <cstdarg>
#include <zlib.h>
#include "lmmsconfig.h"
#include "../globals.h"
#include "Util.h"
struct XmlData
{
XmlData() :
m_doc( "ZynAddSubFX-data" )
{
}
QDomDocument m_doc;
QDomElement m_node;
QDomElement m_info;
QDomElement addparams( const char *name, unsigned int params, ... );
} ;
QtXmlWrapper::QtXmlWrapper() :
d( new XmlData )
{
version.Major = 2;
version.Minor = 4;
version.Revision = 1;
minimal = true;
d->m_node = d->m_doc.createElement( "ZynAddSubFX-data" );
d->m_node.setAttribute( "version-major", QString::number( version.Major ) );
d->m_node.setAttribute( "version-minor", QString::number( version.Minor ) );
d->m_node.setAttribute( "version-revision", QString::number( version.Revision ) );
d->m_node.setAttribute( "ZynAddSubFX-author", "Nasca Octavian Paul" );
d->m_doc.appendChild( d->m_node );
//make the empty branch that will contain the information parameters
d->m_info = d->addparams("INFORMATION", 0);
//save zynaddsubfx specifications
beginbranch("BASE_PARAMETERS");
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_addsynth_voices", NUM_VOICES);
endbranch();
}
QtXmlWrapper::~QtXmlWrapper()
{
delete d;
}
void QtXmlWrapper::setPadSynth(bool enabled)
{
/**@bug this might create multiple nodes when only one is needed*/
QDomElement oldNode = d->m_node;
d->m_node = d->m_info;
//Info storing
addparbool("PADsynth_used", enabled);
d->m_node = oldNode;
}
QDomElement findElement( QDomElement root, const QString & tagname, const QString & attrname,
const QString & attrval )
{
QDomNodeList list = root.elementsByTagName( tagname );
for( int i = 0; i < list.size(); ++i )
{
QDomNode n = list.at( i );
if( n.isElement() )
{
QDomElement e = n.toElement();
if( e.hasAttribute( attrname ) && e.attribute( attrname ) == attrval )
{
return e;
}
}
}
return QDomElement();
}
bool QtXmlWrapper::hasPadSynth() const
{
/**Right now this has a copied implementation of setparbool, so this should
* be reworked as XMLwrapper evolves*/
QDomElement tmp = d->m_doc.elementsByTagName( "INFORMATION" ).at( 0 ).toElement();
QDomElement parameter = findElement( tmp, "par_bool", "name", "PADsynth_used" );
if( !parameter.isNull() )
{
const QString val = parameter.attribute( "value" ).toLower();
return val[0] == 'y';
}
return false;
}
/* SAVE XML members */
int QtXmlWrapper::saveXMLfile(const std::string &filename) const
{
char *xmldata = getXMLdata();
if(xmldata == NULL)
return -2;
int compression = config.cfg.GzipCompression;
int result = dosavefile(filename.c_str(), compression, xmldata);
delete[] xmldata;
return result;
}
char *QtXmlWrapper::getXMLdata() const
{
QString xml = d->m_doc.toString( 1 );
return qstrdup( xml.toUtf8().constData() );
}
int QtXmlWrapper::dosavefile(const char *filename,
int compression,
const char *xmldata) const
{
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);
gzFile gzfile;
gzfile = gzopen(filename, options);
if(gzfile == NULL)
return -1;
gzputs(gzfile, xmldata);
gzclose(gzfile);
}
return 0;
}
void QtXmlWrapper::addpar(const std::string &name, int val)
{
d->addparams("par", 2, "name", name.c_str(), "value", stringFrom<int>(
val).c_str());
}
void QtXmlWrapper::addparreal(const std::string &name, REALTYPE val)
{
d->addparams("par_real", 2, "name", name.c_str(), "value",
stringFrom<REALTYPE>(val).c_str());
}
void QtXmlWrapper::addparbool(const std::string &name, int val)
{
if(val != 0)
d->addparams("par_bool", 2, "name", name.c_str(), "value", "yes");
else
d->addparams("par_bool", 2, "name", name.c_str(), "value", "no");
}
void QtXmlWrapper::addparstr(const std::string &name, const std::string &val)
{
QDomElement e = d->m_doc.createElement( "string" );
e.setAttribute( "name", name.c_str() );
e.appendChild( d->m_doc.createTextNode( val.c_str() ) );
d->m_node.appendChild( e );
}
void QtXmlWrapper::beginbranch(const std::string &name)
{
d->m_node = d->addparams(name.c_str(), 0);
}
void QtXmlWrapper::beginbranch(const std::string &name, int id)
{
d->m_node = d->addparams(name.c_str(), 1, "id", stringFrom<int>(id).c_str());
}
void QtXmlWrapper::endbranch()
{
d->m_node = d->m_node.parentNode().toElement();
}
/* LOAD XML members */
int QtXmlWrapper::loadXMLfile(const std::string &filename)
{
const char *xmldata = doloadfile(filename.c_str());
if(xmldata == NULL)
{
qDebug() << "QtXmlWrapper::loadXMLfile(): empty data";
return -1; //the file could not be loaded or uncompressed
}
QByteArray b( xmldata );
while( !b.isEmpty() && b[0] != '<' )
{
// remove first blank line
b.remove( 0, 1 );
}
if( !d->m_doc.setContent( b ) )
{
qDebug() << "QtXmlWrapper::loadXMLfile(): could not set document content";
delete[] xmldata;
return -2;
}
delete[] xmldata;
d->m_node = d->m_doc.elementsByTagName( "ZynAddSubFX-data" ).at( 0 ).toElement();
if( d->m_node.isNull() || !d->m_node.isElement() )
{
qDebug() << "QtXmlWrapper::loadXMLfile(): missing root node";
return -3; //the XML doesnt embbed zynaddsubfx data
}
QDomElement root = d->m_node.toElement();
//fetch version information
version.Major = root.attribute( "version-major").toInt();
version.Minor = root.attribute( "version-minor").toInt();
version.Revision = root.attribute( "version-revision").toInt();
return 0;
}
char *QtXmlWrapper::doloadfile(const std::string &filename) const
{
char *xmldata = NULL;
gzFile gzfile = gzopen(filename.c_str(), "rb");
if(gzfile != NULL) { //The possibly compressed file opened
std::stringstream strBuf; //reading stream
const int bufSize = 500; //fetch size
char fetchBuf[bufSize + 1]; //fetch buffer
int read = 0; //chars read in last fetch
fetchBuf[bufSize] = 0; //force null termination
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
std::string tmp = strBuf.str();
xmldata = new char[tmp.size() + 1];
strncpy(xmldata, tmp.c_str(), tmp.size() + 1);
}
return xmldata;
}
bool QtXmlWrapper::putXMLdata(const char *xmldata)
{
d->m_doc.setContent( QString::fromUtf8( xmldata ) );
d->m_node = d->m_doc.elementsByTagName( "ZynAddSubFX-data" ).at( 0 ).toElement();
if( d->m_node.isNull() )
{
return false;
}
return true;
}
int QtXmlWrapper::enterbranch(const std::string &name)
{
QDomElement tmp = d->m_node.firstChildElement( name.c_str() );
if( tmp.isNull() )
{
return 0;
}
d->m_node = tmp;
return 1;
}
int QtXmlWrapper::enterbranch(const std::string &name, int id)
{
QDomElement tmp = findElement( d->m_node, name.c_str(),
"id", QString::number( id ) );
if( tmp.isNull() )
{
return 0;
}
d->m_node = tmp;
return 1;
}
void QtXmlWrapper::exitbranch()
{
d->m_node = d->m_node.parentNode().toElement();
}
int QtXmlWrapper::getbranchid(int min, int max) const
{
if( !d->m_node.isElement() )
{
return min;
}
QDomElement tmp = d->m_node.toElement();
if( !tmp.hasAttribute( "id" ) )
{
return min;
}
int id = tmp.attribute( "id" ).toInt();
if((min == 0) && (max == 0))
return id;
if(id < min)
id = min;
else
if(id > max)
id = max;
return id;
}
int QtXmlWrapper::getpar(const std::string &name, int defaultpar, int min,
int max) const
{
QDomElement tmp = findElement( d->m_node, "par", "name", name.c_str() );
if( tmp.isNull() || !tmp.hasAttribute( "value" ) )
{
return defaultpar;
}
int val = tmp.attribute( "value" ).toInt();
if(val < min)
val = min;
else
if(val > max)
val = max;
return val;
}
int QtXmlWrapper::getpar127(const std::string &name, int defaultpar) const
{
return getpar(name, defaultpar, 0, 127);
}
int QtXmlWrapper::getparbool(const std::string &name, int defaultpar) const
{
QDomElement tmp = findElement( d->m_node, "par_bool", "name", name.c_str() );
if( tmp.isNull() || !tmp.hasAttribute( "value" ) )
{
return defaultpar;
}
const QString val = tmp.attribute( "value" ).toLower();
if( val[0] == 'y' )
{
return 1;
}
return 0;
}
void QtXmlWrapper::getparstr(const std::string &name, char *par, int maxstrlen) const
{
ZERO(par, maxstrlen);
QDomNode tmp = findElement( d->m_node, "string", "name", name.c_str() );
if( tmp.isNull() || !tmp.hasChildNodes() )
{
return;
}
tmp = tmp.firstChild();
if( tmp.nodeType() == QDomNode::ElementNode )
{
snprintf(par, maxstrlen, "%s", tmp.toElement().tagName().toUtf8().constData() );
return;
}
if( tmp.nodeType() == QDomNode::TextNode )
{
snprintf(par, maxstrlen, "%s", tmp.toText().data().toUtf8().constData() );
return;
}
}
std::string QtXmlWrapper::getparstr(const std::string &name,
const std::string &defaultpar) const
{
QDomNode tmp = findElement( d->m_node, "string", "name", name.c_str() );
if( tmp.isNull() || !tmp.hasChildNodes() )
{
return defaultpar;
}
tmp = tmp.firstChild();
if( tmp.nodeType() == QDomNode::ElementNode && !tmp.toElement().tagName().isEmpty() )
{
return tmp.toElement().tagName().toUtf8().constData();
}
if( tmp.nodeType() == QDomNode::TextNode && !tmp.toText().data().isEmpty() )
{
return tmp.toText().data().toUtf8().constData();
}
return defaultpar;
}
REALTYPE QtXmlWrapper::getparreal(const char *name, REALTYPE defaultpar) const
{
QDomElement tmp = findElement( d->m_node, "par_real", "name", name );
if( tmp.isNull() || !tmp.hasAttribute( "value" ) )
{
return defaultpar;
}
return tmp.attribute( "value" ).toFloat();
}
REALTYPE QtXmlWrapper::getparreal(const char *name,
REALTYPE defaultpar,
REALTYPE min,
REALTYPE max) const
{
REALTYPE result = getparreal(name, defaultpar);
if(result < min)
result = min;
else
if(result > max)
result = max;
return result;
}
/** Private members **/
QDomElement XmlData::addparams(const char *name, unsigned int params,
...)
{
/**@todo make this function send out a good error message if something goes
* wrong**/
QDomElement element = m_doc.createElement( name );
m_node.appendChild( element );
if(params) {
va_list variableList;
va_start(variableList, params);
const char *ParamName;
const char *ParamValue;
while(params--) {
ParamName = va_arg(variableList, const char *);
ParamValue = va_arg(variableList, const char *);
element.setAttribute( ParamName, ParamValue);
}
}
return element;
}

View File

@@ -1,125 +0,0 @@
/*
* QtXmlWrapper.h - a QtXml based XML backend for ZynAddSubxFX
*
* Copyright (c) 2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
/* File derived from XMLwrapper.h: */
/*
ZynAddSubFX - a software synthesizer
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
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 QT_XML_WRAPPER_H
#define QT_XML_WRAPPER_H
#include "../globals.h"
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#define QtXmlWrapper XMLwrapper
struct XmlData;
class QtXmlWrapper
{
public:
QtXmlWrapper();
~QtXmlWrapper();
int saveXMLfile( const std::string & filename ) const;
int loadXMLfile( const std::string & filename );
char *getXMLdata() const;
bool putXMLdata( const char *xmldata );
void addpar( const std::string & name, int val );
void addparreal( const std::string & name, REALTYPE val);
void addparbool( const std::string & name, int val );
void addparstr( const std::string & name, const std::string & val );
void beginbranch( const std::string & name );
void beginbranch( const std::string & name, int id );
void endbranch();
int enterbranch( const std::string & name );
int enterbranch( const std::string & name, int id );
void exitbranch();
int getbranchid( int min, int max ) const;
int getpar( const std::string & name, int defaultpar, int min, int max ) const;
int getpar127( const std::string & name, int defaultpar ) const;
int getparbool( const std::string & name, int defaultpar ) const;
void getparstr( const std::string & name, char * par, int maxstrlen ) const;
std::string getparstr( const std::string & name, const std::string & defaultpar ) const;
REALTYPE getparreal( const char * name, REALTYPE defaultpar ) const;
REALTYPE getparreal(const char *name, REALTYPE defaultpar, REALTYPE min, REALTYPE max) const;
bool minimal; /**<false if all parameters will be stored (used only for clipboard)*/
void setPadSynth( bool enabled );
bool hasPadSynth() const;
private:
int dosavefile(const char *filename, int compression, const char *xmldata) const;
char *doloadfile(const std::string &filename) const;
struct
{
int Major;
int Minor;
int Revision;
} version;
XmlData * d;
};
#endif

View File

@@ -1,39 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Stereo.cpp - 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)
:l(left), r(right)
{}
template<class T>
Stereo<T>::Stereo(const T &val)
:l(val), r(val)
{}
template<class T>
Stereo<T> &Stereo<T>::operator=(const Stereo<T> &nstr)
{
l = nstr.l;
r = nstr.r;
return *this;
}

View File

@@ -1,42 +0,0 @@
/*
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>
struct 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() {}
Stereo<T> &operator=(const Stereo<T> &smp);
//data
T l, r;
};
#include "Stereo.cpp"
#endif

View File

@@ -1,130 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Util.cpp - 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
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 "Util.h"
#include <math.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int SAMPLE_RATE = 44100;
int SOUND_BUFFER_SIZE = 256;
int OSCIL_SIZE = 1024;
Config config;
REALTYPE *denormalkillbuf;
/*
* Transform the velocity according the scaling parameter (velocity sensing)
*/
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);
}
/*
* Get the detune in cents
*/
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;
if(octave >= 8)
octave -= 16;
octdet = octave * 1200.0;
//Coarse and fine detune
int cdetune = coarsedetune % 1024;
if(cdetune > 512)
cdetune -= 1024;
int fdetune = finedetune - 8192;
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;
}
if(finedetune < 8192)
findet = -findet;
if(cdetune < 0)
cdet = -cdet;
det = octdet + cdet + findet;
return det;
}
bool fileexists(const char *filename)
{
struct stat tmp;
int result = stat(filename, &tmp);
if(result >= 0)
return true;
return false;
}
void invSignal(REALTYPE *sig, size_t len)
{
for(unsigned int i = 0; i < len; i++)
sig[i] *= -1.0f;
}
void crossover(REALTYPE &a, REALTYPE &b, REALTYPE crossover)
{
REALTYPE tmpa = a;
REALTYPE tmpb = b;
a = tmpa * (1.0 - crossover) + tmpb * crossover;
b = tmpb * (1.0 - crossover) + tmpa * crossover;
}

View File

@@ -1,84 +0,0 @@
/*
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
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 UTIL_H
#define UTIL_H
#include <cstdio>
#include <string>
#include <sstream>
#include "../globals.h"
#include "Config.h"
//Velocity Sensing function
extern REALTYPE VelF(REALTYPE velocity, unsigned char scaling);
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 Config config;
void invSignal(REALTYPE *sig, size_t len);
void crossover(REALTYPE &a, REALTYPE &b, REALTYPE crossover);
template<class T>
std::string stringFrom(T x)
{
std::stringstream ss;
ss << x;
return ss.str();
}
template<class T>
std::string stringFrom(REALTYPE x)
{
char buf[64];
sprintf( buf, "%f", x );
return buf;
}
template<class T>
T stringTo(const char *x)
{
std::string str = x != NULL ? x : "0"; //should work for the basic float/int
std::stringstream ss(str);
T ans;
ss >> ans;
return ans;
}
template <class T>
T limit(T val, T min, T max)
{
return (val < min ? min : (val > max ? max : val));
}
#endif

View File

@@ -1,617 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
XMLwrapper.cpp - 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
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 "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;
bool verbose = false;
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";
;
return 0;
}
//temporary const overload of mxmlFindElement
const mxml_node_t *mxmlFindElement(const mxml_node_t *node,
const mxml_node_t *top,
const char *name,
const char *attr,
const char *value,
int descend)
{
return const_cast<const mxml_node_t *>(mxmlFindElement(
const_cast<mxml_node_t *>(node),
const_cast<mxml_node_t *>(top),
name, attr, value, descend));
}
//temporary const overload of mxmlElementGetAttr
const char *mxmlElementGetAttr(const mxml_node_t *node, const char *name)
{
return mxmlElementGetAttr(const_cast<mxml_node_t *>(node), name);
}
XMLwrapper::XMLwrapper()
{
version.Major = 2;
version.Minor = 4;
version.Revision = 1;
minimal = true;
node = 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");
*/
mxml_node_t *doctype = mxmlNewElement(tree, "!DOCTYPE");
mxmlElementSetAttr(doctype, "ZynAddSubFX-data", NULL);
node = root = addparams("ZynAddSubFX-data", 4,
"version-major", stringFrom<int>(
version.Major).c_str(),
"version-minor", stringFrom<int>(
version.Minor).c_str(),
"version-revision",
stringFrom<int>(version.Revision).c_str(),
"ZynAddSubFX-author", "Nasca Octavian Paul");
//make the empty branch that will contain the information parameters
info = addparams("INFORMATION", 0);
//save zynaddsubfx specifications
beginbranch("BASE_PARAMETERS");
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_addsynth_voices", NUM_VOICES);
endbranch();
}
XMLwrapper::~XMLwrapper()
{
if(tree != NULL)
mxmlDelete(tree);
}
void XMLwrapper::setPadSynth(bool enabled)
{
/**@bug this might create multiple nodes when only one is needed*/
mxml_node_t *oldnode = node;
node = info;
//Info storing
addparbool("PADsynth_used", enabled);
node = oldnode;
}
bool XMLwrapper::hasPadSynth() const
{
/**Right now this has a copied implementation of setparbool, so this should
* be reworked as XMLwrapper evolves*/
mxml_node_t *tmp = mxmlFindElement(tree,
tree,
"INFORMATION",
NULL,
NULL,
MXML_DESCEND);
mxml_node_t *parameter = mxmlFindElement(tmp,
tmp,
"par_bool",
"name",
"PADsynth_used",
MXML_DESCEND_FIRST);
if(parameter == NULL) //no information availiable
return false;
const char *strval = mxmlElementGetAttr(parameter, "value");
if(strval == NULL) //no information available
return false;
if((strval[0] == 'Y') || (strval[0] == 'y'))
return true;
else
return false;
}
/* SAVE XML members */
int XMLwrapper::saveXMLfile(const string &filename) const
{
char *xmldata = getXMLdata();
if(xmldata == NULL)
return -2;
int compression = config.cfg.GzipCompression;
int result = dosavefile(filename.c_str(), compression, xmldata);
free(xmldata);
return result;
}
char *XMLwrapper::getXMLdata() const
{
xml_k = 0;
char *xmldata = mxmlSaveAllocString(tree, XMLwrapper_whitespace_callback);
return xmldata;
}
int XMLwrapper::dosavefile(const char *filename,
int compression,
const char *xmldata) const
{
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);
gzFile gzfile;
gzfile = gzopen(filename, options);
if(gzfile == NULL)
return -1;
gzputs(gzfile, xmldata);
gzclose(gzfile);
}
return 0;
}
void XMLwrapper::addpar(const string &name, int val)
{
addparams("par", 2, "name", name.c_str(), "value", stringFrom<int>(
val).c_str());
}
void XMLwrapper::addparreal(const string &name, REALTYPE val)
{
addparams("par_real", 2, "name", name.c_str(), "value",
stringFrom<REALTYPE>(val).c_str());
}
void XMLwrapper::addparbool(const string &name, int val)
{
if(val != 0)
addparams("par_bool", 2, "name", name.c_str(), "value", "yes");
else
addparams("par_bool", 2, "name", name.c_str(), "value", "no");
}
void XMLwrapper::addparstr(const string &name, const string &val)
{
mxml_node_t *element = mxmlNewElement(node, "string");
mxmlElementSetAttr(element, "name", name.c_str());
mxmlNewText(element, 0, val.c_str());
}
void XMLwrapper::beginbranch(const string &name)
{
if(verbose)
cout << "beginbranch()" << name << endl;
node = addparams(name.c_str(), 0);
}
void XMLwrapper::beginbranch(const string &name, int id)
{
if(verbose)
cout << "beginbranch(" << id << ")" << name << endl;
node = addparams(name.c_str(), 1, "id", stringFrom<int>(id).c_str());
}
void XMLwrapper::endbranch()
{
if(verbose)
cout << "endbranch()" << node << "-" << node->value.element.name
<< " To "
<< node->parent << "-" << node->parent->value.element.name << endl;
node = node->parent;
}
/* LOAD XML members */
int XMLwrapper::loadXMLfile(const string &filename)
{
if(tree != NULL)
mxmlDelete(tree);
tree = NULL;
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
//fetch version information
version.Major = stringTo<int>(mxmlElementGetAttr(root, "version-major"));
version.Minor = stringTo<int>(mxmlElementGetAttr(root, "version-minor"));
version.Revision =
stringTo<int>(mxmlElementGetAttr(root, "version-revision"));
if(verbose)
cout << "loadXMLfile() version: " << version.Major << '.'
<< version.Minor << '.' << version.Revision << endl;
return 0;
}
char *XMLwrapper::doloadfile(const string &filename) const
{
char *xmldata = NULL;
gzFile gzfile = gzopen(filename.c_str(), "rb");
if(gzfile != NULL) { //The possibly compressed file opened
stringstream strBuf; //reading stream
const int bufSize = 500; //fetch size
char fetchBuf[bufSize + 1]; //fetch buffer
int read = 0; //chars read in last fetch
fetchBuf[bufSize] = 0; //force null termination
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;
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;
return true;
}
int XMLwrapper::enterbranch(const string &name)
{
if(verbose)
cout << "enterbranch() " << name << endl;
mxml_node_t *tmp = mxmlFindElement(node, node,
name.c_str(), NULL, NULL,
MXML_DESCEND_FIRST);
if(tmp == NULL)
return 0;
node = tmp;
return 1;
}
int XMLwrapper::enterbranch(const string &name, int id)
{
if(verbose)
cout << "enterbranch(" << id << ") " << name << endl;
mxml_node_t *tmp = mxmlFindElement(node, node,
name.c_str(), "id", stringFrom<int>(
id).c_str(), MXML_DESCEND_FIRST);
if(tmp == NULL)
return 0;
node = tmp;
return 1;
}
void XMLwrapper::exitbranch()
{
if(verbose)
cout << "exitbranch()" << node << "-" << node->value.element.name
<< " To "
<< node->parent << "-" << node->parent->value.element.name << endl;
node = node->parent;
}
int XMLwrapper::getbranchid(int min, int max) const
{
int id = stringTo<int>(mxmlElementGetAttr(node, "id"));
if((min == 0) && (max == 0))
return id;
if(id < min)
id = min;
else
if(id > max)
id = max;
return id;
}
int XMLwrapper::getpar(const string &name, int defaultpar, int min,
int max) const
{
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"par",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
if(tmp == NULL)
return defaultpar;
const char *strval = mxmlElementGetAttr(tmp, "value");
if(strval == NULL)
return defaultpar;
int val = stringTo<int>(strval);
if(val < min)
val = min;
else
if(val > max)
val = max;
return val;
}
int XMLwrapper::getpar127(const string &name, int defaultpar) const
{
return getpar(name, defaultpar, 0, 127);
}
int XMLwrapper::getparbool(const string &name, int defaultpar) const
{
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"par_bool",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
if(tmp == NULL)
return defaultpar;
const char *strval = mxmlElementGetAttr(tmp, "value");
if(strval == NULL)
return defaultpar;
if((strval[0] == 'Y') || (strval[0] == 'y'))
return 1;
else
return 0;
}
void XMLwrapper::getparstr(const string &name, char *par, int maxstrlen) const
{
ZERO(par, maxstrlen);
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"string",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
if(tmp == NULL)
return;
if(tmp->child == NULL)
return;
if(tmp->child->type == MXML_OPAQUE) {
snprintf(par, maxstrlen, "%s", tmp->child->value.element.name);
return;
}
if((tmp->child->type == MXML_TEXT)
&& (tmp->child->value.text.string != NULL)) {
snprintf(par, maxstrlen, "%s", tmp->child->value.text.string);
return;
}
}
string XMLwrapper::getparstr(const string &name,
const std::string &defaultpar) const
{
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"string",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
if((tmp == NULL) || (tmp->child == NULL))
return defaultpar;
if((tmp->child->type == MXML_OPAQUE)
&& (tmp->child->value.element.name != NULL))
return tmp->child->value.element.name;
if((tmp->child->type == MXML_TEXT)
&& (tmp->child->value.text.string != NULL))
return tmp->child->value.text.string;
return defaultpar;
}
REALTYPE XMLwrapper::getparreal(const char *name, REALTYPE defaultpar) const
{
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"par_real",
"name",
name,
MXML_DESCEND_FIRST);
if(tmp == NULL)
return defaultpar;
const char *strval = mxmlElementGetAttr(tmp, "value");
if(strval == NULL)
return defaultpar;
return stringTo<REALTYPE>(strval);
}
REALTYPE XMLwrapper::getparreal(const char *name,
REALTYPE defaultpar,
REALTYPE min,
REALTYPE max) const
{
REALTYPE result = getparreal(name, defaultpar);
if(result < min)
result = min;
else
if(result > max)
result = max;
return result;
}
/** Private members **/
mxml_node_t *XMLwrapper::addparams(const char *name, unsigned int params,
...) const
{
/**@todo make this function send out a good error message if something goes
* wrong**/
mxml_node_t *element = mxmlNewElement(node, name);
if(params) {
va_list variableList;
va_start(variableList, params);
const char *ParamName;
const char *ParamValue;
while(params--) {
ParamName = va_arg(variableList, const char *);
ParamValue = va_arg(variableList, const char *);
if(verbose)
cout << "addparams()[" << params << "]=" << name << " "
<< ParamName << "=\"" << ParamValue << "\"" << endl;
mxmlElementSetAttr(element, ParamName, ParamValue);
}
}
return element;
}

View File

@@ -1,275 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
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
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
*/
#if 1
#include "QtXmlWrapper.h"
#else
#include <mxml.h>
#include <string>
#ifndef REALTYPE
#define REALTYPE float
#endif
#ifndef XML_WRAPPER_H
#define XML_WRAPPER_H
/**Mxml wrapper*/
class XMLwrapper
{
public:
/**
* Constructor.
* Will Construct the object and fill in top level branch
* */
XMLwrapper();
/**Destructor*/
~XMLwrapper();
/**
* 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) const;
/**
* 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() const;
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**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();
/**
* 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);
/**
* Loads string into XMLwrapper.
* @param xmldata NULL terminated string of XML data.
* @returns true if successful.
*/
bool putXMLdata(const char *xmldata);
/**
* Enters the branch.
* @param name Name of branch.
* @returns 1 if is ok, or 0 otherwise.
*/
int enterbranch(const std::string &name);
/**
* 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);
/**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) const;
/**
* 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) const;
/**
* 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) const;
/**
* 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) const;
/**
* 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) const;
/**
* Get the string value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
std::string getparstr(const std::string &name,
const std::string &defaultpar) const;
/**
* 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) const;
/**
* 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) const;
bool minimal; /**<false if all parameters will be stored (used only for clipboard)*/
/**
* Sets the current tree's PAD Synth usage
*/
void setPadSynth(bool enabled);
/**
* Checks the current tree for PADsynth usage
*/
bool hasPadSynth() const;
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) const;
/**
* 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) const;
mxml_node_t *tree; /**<all xml data*/
mxml_node_t *root; /**<xml data used by zynaddsubfx*/
mxml_node_t *node; /**<current subtree in parsing or writing */
mxml_node_t *info; /**<Node used to store the information about the data*/
/**
* Create mxml_node_t with specified name and parameters
*
* Results should look like:
* <name optionalParam1="value1" optionalParam2="value2" ...>
*
* @param name The name of the xml node
* @param params The number of the attributes
* @param ... const char * pairs that are in the format attribute_name,
* attribute_value
*/
mxml_node_t *addparams(const char *name, unsigned int params,
...) const;
/**@todo keep these numbers up to date*/
struct {
int Major; /**<major version number.*/
int Minor; /**<minor version number.*/
int Revision; /**<version revision number.*/
} version;
};
#endif
#endif

View File

@@ -1,33 +0,0 @@
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})

View File

@@ -1,685 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
DSSIaudiooutput.cpp - 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
*/
/*
* Inital working DSSI output code contributed by Stephen G. Parry
*/
//this file contains code used from trivial_synth.c from
//the DSSI (published by Steve Harris under public domain) as a template.
#include <string.h>
#include "DSSIaudiooutput.h"
#include "../Misc/Config.h"
#include "../Misc/Bank.h"
#include <limits.h>
//
// Static stubs for LADSPA member functions
//
// LADSPA is essentially a C handle based API; This plug-in implementation is
// a C++ OO one so we need stub functions to map from C API calls to C++ object
// method calls.
void DSSIaudiooutput::stub_connectPort(LADSPA_Handle instance, unsigned long port, LADSPA_Data * data)
{
getInstance(instance)->connectPort(port, data);
}
void DSSIaudiooutput::stub_activate(LADSPA_Handle instance)
{
getInstance(instance)->activate();
}
void DSSIaudiooutput::stub_run(LADSPA_Handle instance, unsigned long sample_count)
{
getInstance(instance)->run(sample_count);
}
void DSSIaudiooutput::stub_deactivate(LADSPA_Handle instance)
{
getInstance(instance)->deactivate();
}
void DSSIaudiooutput::stub_cleanup(LADSPA_Handle instance)
{
DSSIaudiooutput* plugin_instance = getInstance(instance);
plugin_instance->cleanup();
delete plugin_instance;
}
const LADSPA_Descriptor *ladspa_descriptor(unsigned long index)
{
return DSSIaudiooutput::getLadspaDescriptor(index);
}
//
// Static stubs for DSSI member functions
//
// DSSI is essentially a C handle based API; This plug-in implementation is
// a C++ OO one so we need stub functions to map from C API calls to C++ object
// method calls.
const DSSI_Program_Descriptor* DSSIaudiooutput::stub_getProgram (LADSPA_Handle instance, unsigned long index)
{
return getInstance(instance)->getProgram(index);
}
void DSSIaudiooutput::stub_selectProgram(LADSPA_Handle instance, unsigned long bank, unsigned long program)
{
getInstance(instance)->selectProgram(bank, program);
}
int DSSIaudiooutput::stub_getMidiControllerForPort(LADSPA_Handle instance, unsigned long port)
{
return getInstance(instance)->getMidiControllerForPort(port);
}
void DSSIaudiooutput::stub_runSynth(LADSPA_Handle instance, unsigned long sample_count,
snd_seq_event_t *events, unsigned long event_count)
{
getInstance(instance)->runSynth(sample_count, events, event_count);
}
const DSSI_Descriptor *dssi_descriptor(unsigned long index)
{
return DSSIaudiooutput::getDssiDescriptor(index);
}
//
// LADSPA member functions
//
/**
* Instantiates a plug-in.
*
* This LADSPA member function instantiates a plug-in.
* Note that instance initialisation should generally occur in
* activate() rather than here.
*
* Zyn Implementation
* ------------------
* This implementation creates a C++ class object and hides its pointer
* in the handle by type casting.
*
* @param descriptor [in] the descriptor for this plug-in
* @param s_rate [in] the sample rate
* @return the plug-in instance handle if successful else NULL
*/
LADSPA_Handle DSSIaudiooutput::instantiate(const LADSPA_Descriptor * descriptor, unsigned long s_rate)
{
if(descriptor->UniqueID == dssiDescriptor->LADSPA_Plugin->UniqueID)
{
return (LADSPA_Handle)(new DSSIaudiooutput(s_rate));
}
else
{
return NULL;
}
}
/**
* Connects a port on an instantiated plug-in.
*
* This LADSPA member function connects a port on an instantiated plug-in to a
* memory location at which a block of data for the port will be read/written.
* The data location is expected to be an array of LADSPA_Data for audio ports
* or a single LADSPA_Data value for control ports. Memory issues will be
* managed by the host. The plug-in must read/write the data at these locations
* every time run() or run_adding() is called and the data present at the time
* of this connection call should not be considered meaningful.
*
* Zyn Implementation
* ------------------
* The buffer pointers are stored as member variables
*
* @param port [in] the port to be connected
* @param data [in] the data buffer to write to / read from
*/
void DSSIaudiooutput::connectPort(unsigned long port, LADSPA_Data * data)
{
switch (port) {
case 0:
outl = data;
break;
case 1:
outr = data;
break;
}
}
/**
* Initialises a plug-in instance and activates it for use.
*
* This LADSPA member function initialises a plug-in instance and activates it
* for use. This is separated from instantiate() to aid real-time support and
* so that hosts can reinitialise a plug-in instance by calling deactivate() and
* then activate(). In this case the plug-in instance must reset all state
* information dependent on the history of the plug-in instance except for any
* data locations provided by connect_port() and any gain set by
* set_run_adding_gain().
*
* Zyn Implementation
* ------------------
* Currently this does nothing; Care must be taken as to code placed here as
* too much code here seems to cause time-out problems in jack-dssi-host.
*/
void DSSIaudiooutput::activate()
{
}
/**
* Runs an instance of a plug-in for a block.
*
* This LADSPA member function runs an instance of a plug-in for a block.
* Note that if an activate() function exists then it must be called before
* run() or run_adding(). If deactivate() is called for a plug-in instance then
* the plug-in instance may not be reused until activate() has been called again.
*
* Zyn Implementation
* ------------------
* This is a LADSPA function that does not process any MIDI events; it is hence
* implemented by simply calling runSynth() with an empty event list.
*
* @param sample_count [in] the block size (in samples) for which the plug-in instance may run
*/
void DSSIaudiooutput::run(unsigned long sample_count)
{
runSynth(sample_count,NULL,(unsigned long)0);
}
/**
* Counterpart to activate().
*
* This LADSPA member function is the counterpart to activate() (see above).
* Deactivation is not similar to pausing as the plug-in instance will be
* reinitialised when activate() is called to reuse it.
*
* Zyn Implementation
* ------------------
* Currently this function does nothing.
*/
void DSSIaudiooutput::deactivate()
{
}
/**
* Deletes a plug-in instance that is no longer required.
*
* LADSPA member function; once an instance of a plug-in has been finished with
* it can be deleted using this function. The instance handle ceases to be
* valid after this call.
*
* If activate() was called for a plug-in instance then a corresponding call to
* deactivate() must be made before cleanup() is called.
*
* Zyn Implementation
* ------------------
* Currently cleanup is deferred to the destructor that is invoked after cleanup()
*/
void DSSIaudiooutput::cleanup()
{
}
/**
* Initial entry point for the LADSPA plug-in library.
*
* This LADSPA function is the initial entry point for the plug-in library.
* The LADSPA host looks for this entry point in each shared library object it
* finds and then calls the function to enumerate the plug-ins within the
* library.
*
* Zyn Implementation
* ------------------
* As the Zyn plug-in is a DSSI plug-in, the LADSPA descriptor is embedded inside
* the DSSI descriptor, which is created by DSSIaudiooutput::initDssiDescriptor()
* statically when the library is loaded. This function then merely returns a pointer
* to that embedded descriptor.
*
* @param index [in] the index number of the plug-in within the library.
* @return if index is in range, a pointer to the plug-in descriptor is returned, else NULL
*/
const LADSPA_Descriptor* DSSIaudiooutput::getLadspaDescriptor(unsigned long index)
{
if(index > 0 || dssiDescriptor == NULL)
return NULL;
else
return dssiDescriptor->LADSPA_Plugin;
}
//
// DSSI member functions
//
/**
* Provides a description of a program available on this synth.
*
* This DSSI member function pointer provides a description of a program (named
* preset sound) available on this synth.
*
* Zyn Implementation
* ------------------
* The instruments in all Zyn's bank directories, as shown by the `instrument
* -> show instrument bank` command, are enumerated to the host by this
* function, allowing access to all those instruments.
* The first time an instrument is requested, the bank it is in and any
* unmapped ones preceding that are mapped; all the instruments names and
* filenames from those banks are stored in the programMap member variable for
* later use. This is done on demand in this way, rather than up front in one
* go because loading all the instrument names in one go can lead to timeouts
* and zombies.
*
* @param index [in] index into the plug-in's list of
* programs, not a program number as represented by the Program
* field of the DSSI_Program_Descriptor. (This distinction is
* needed to support synths that use non-contiguous program or
* bank numbers.)
* @return a DSSI_Program_Descriptor pointer that is
* guaranteed to be valid only until the next call to get_program,
* deactivate, or configure, on the same plug-in instance, or NULL if index is out of range.
*/
const DSSI_Program_Descriptor* DSSIaudiooutput::getProgram (unsigned long index)
{
static DSSI_Program_Descriptor retVal;
/* Make sure we have the list of banks loaded */
initBanks();
/* Make sure that the bank containing the instrument has been mapped */
while (index >= programMap.size() && mapNextBank())
/* DO NOTHING MORE */;
if(index >= programMap.size())
{
/* No more instruments */
return NULL;
}
else
{
/* OK, return the instrument */
retVal.Name = programMap[index].name.c_str();
retVal.Program = programMap[index].program;
retVal.Bank = programMap[index].bank;
return &retVal;
}
}
/**
* Selects a new program for this synth.
*
* This DSSI member function selects a new program for this synth. The program
* change will take effect immediately at the start of the next run_synth()
* call. An invalid bank / instrument combination is ignored.
*
* Zyn Implementation
* ------------------
* the banks and instruments are as shown in the `instrument -> show instrument
* bank` command in Zyn. The bank no is a 1-based index into the list of banks
* Zyn loads and shows in the drop down and the program number is the
* instrument within that bank.
*
* @param bank [in] the bank number to select
* @param program [in] the program number within the bank to select
*/
void DSSIaudiooutput::selectProgram(unsigned long bank, unsigned long program)
{
initBanks();
// cerr << "selectProgram(" << (bank & 0x7F) << ':' << ((bank >> 7) & 0x7F) << "," << program << ")" << '\n';
if(bank < MAX_NUM_BANKS && program < BANK_SIZE)
{
char* bankdir = master->bank.banks[ bank ].dir;
if(bankdir != NULL)
{
pthread_mutex_lock(&master->mutex);
/* We have to turn off the CheckPADsynth functionality, else
* the program change takes way too long and we get timeouts
* and hence zombies (!) */
int save = config.cfg.CheckPADsynth;
config.cfg.CheckPADsynth = 0;
/* Load the bank... */
master->bank.loadbank(bankdir);
/* restore the CheckPADsynth flag */
config.cfg.CheckPADsynth = save;
/* Now load the instrument... */
master->bank.loadfromslot((unsigned int)program, master->part[0]);
pthread_mutex_unlock(&master->mutex);
}
}
}
/**
* Returns the MIDI controller number or NRPN for a input control port
*
* This DSSI member function returns the MIDI controller number or NRPN that
* should be mapped to the given input control port. If the given port should
* not have any MIDI controller mapped to it, the function will return DSSI_NONE.
* The behaviour of this function is undefined if the given port
* number does not correspond to an input control port.
*
* Zyn Implementation
* ------------------
* Currently Zyn does not define any controller ports, but may do in the future.
*
* @param port [in] the input controller port
* @return the CC and NRPN values shifted and ORed together.
*/
int DSSIaudiooutput::getMidiControllerForPort(unsigned long port)
{
return DSSI_NONE;
}
/**
* Runs the synth for a block.
*
* This DSSI member function runs the synth for a block. This is identical in
* function to the LADSPA run() function, except that it also supplies events
* to the synth.
*
* Zyn Implementation
* ------------------
* Zyn implements synthesis in Master::GetAudioOutSamples; runSynth calls this
* function in chunks delimited by the sample_count and the frame indexes in
* the events block, calling the appropriate NoteOn, NoteOff and SetController
* members of Master to process the events supplied between each chunk.
*
* @param sample_count [in] the block size (in samples) for which the synth
* instance may run.
* @param events [in] The Events pointer points to a block of ALSA
* sequencer events, used to communicate MIDI and related events to the synth.
* Each event must be timestamped relative to the start of the block,
* (mis)using the ALSA "tick time" field as a frame count. The host is
* responsible for ensuring that events with differing timestamps are already
* ordered by time. Must not include NOTE (only NOTE_ON / NOTE_OFF), LSB or MSB
* events.
* @param event_count [in] the number of entries in the `events` block
*/
void DSSIaudiooutput::runSynth(unsigned long sample_count, snd_seq_event_t *events, unsigned long event_count)
{
unsigned long from_frame = 0;
unsigned long event_index = 0;
unsigned long next_event_frame = 0;
unsigned long to_frame = 0;
pthread_mutex_lock(&master->mutex);
do {
/* Find the time of the next event, if any */
if(events == NULL || event_index >= event_count)
next_event_frame = ULONG_MAX;
else
next_event_frame = events[event_index].time.tick;
/* find the end of the sub-sample to be processed this time round... */
/* if the next event falls within the desired sample interval... */
if(next_event_frame < sample_count && next_event_frame >= to_frame)
/* set the end to be at that event */
to_frame = next_event_frame;
else
/* ...else go for the whole remaining sample */
to_frame = sample_count;
if(from_frame<to_frame)
{
// call master to fill from `from_frame` to `to_frame`:
master->GetAudioOutSamples(to_frame - from_frame, (int)sampleRate, &(outl[from_frame]), &(outr[from_frame]));
// next sub-sample please...
from_frame = to_frame;
}
// Now process any event(s) at the current timing point
while(events != NULL && event_index < event_count && events[event_index].time.tick == to_frame)
{
if(events[event_index].type == SND_SEQ_EVENT_NOTEON)
{
master->NoteOn(events[event_index].data.note.channel, events[event_index].data.note.note, events[event_index].data.note.velocity);
}
else if(events[event_index].type == SND_SEQ_EVENT_NOTEOFF)
{
master->NoteOff(events[event_index].data.note.channel, events[event_index].data.note.note);
}
else if(events[event_index].type == SND_SEQ_EVENT_CONTROLLER)
{
master->SetController(events[event_index].data.control.channel, events[event_index].data.control.param, events[event_index].data.control.value);
}
else
{
}
event_index++;
}
// Keep going until we have the desired total length of sample...
} while(to_frame < sample_count);
pthread_mutex_unlock(&master->mutex);
}
/**
* Initial entry point for the DSSI plug-in library.
*
* This DSSI function is the initial entry point for the plug-in library.
* The DSSI host looks for this entry point in each shared library object it
* finds and then calls the function to enumerate the plug-ins within the
* library.
*
* Zyn Implementation
* ------------------
* The descriptor is created statically by DSSIaudiooutput::initDssiDescriptor()
* when the plug-in library is loaded. This function merely returns a pointer to
* that descriptor.
*
* @param index [in] the index number of the plug-in within the library.
* @return if index is in range, a pointer to the plug-in descriptor is returned, else NULL
*/
const DSSI_Descriptor* DSSIaudiooutput::getDssiDescriptor(unsigned long index)
{
if(index > 0 || dssiDescriptor == NULL)
return NULL;
else
return dssiDescriptor;
}
//
// Internal member functions
//
// Initialise the DSSI descriptor, statically:
DSSI_Descriptor* DSSIaudiooutput::dssiDescriptor = DSSIaudiooutput::initDssiDescriptor();
/**
* Initializes the DSSI (and LADSPA) descriptor, returning it is an object.
*/
DSSI_Descriptor* DSSIaudiooutput::initDssiDescriptor()
{
DSSI_Descriptor* newDssiDescriptor = new DSSI_Descriptor;
LADSPA_PortDescriptor* newPortDescriptors;
char** newPortNames;
LADSPA_PortRangeHint* newPortRangeHints;
if (newDssiDescriptor)
{
LADSPA_Descriptor* newLadspaDescriptor = new LADSPA_Descriptor;
if (newLadspaDescriptor)
{
newLadspaDescriptor->UniqueID = 100;
newLadspaDescriptor->Label = "ZASF";
newLadspaDescriptor->Properties = 0;
newLadspaDescriptor->Name = "ZynAddSubFX";
newLadspaDescriptor->Maker = "Nasca Octavian Paul <zynaddsubfx@yahoo.com>";
newLadspaDescriptor->Copyright = "GNU General Public License v.2";
newLadspaDescriptor->PortCount = 2;
newPortNames = new char *[newLadspaDescriptor->PortCount];
newPortNames[0] = "Output L";
newPortNames[1] = "Output R";
newLadspaDescriptor->PortNames = newPortNames;
newPortDescriptors = new LADSPA_PortDescriptor[newLadspaDescriptor->PortCount];
newPortDescriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
newPortDescriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
newLadspaDescriptor->PortDescriptors = newPortDescriptors;
newPortRangeHints = new LADSPA_PortRangeHint[newLadspaDescriptor->PortCount];
newPortRangeHints[0].HintDescriptor = 0;
newPortRangeHints[1].HintDescriptor = 0;
newLadspaDescriptor->PortRangeHints = newPortRangeHints;
newLadspaDescriptor->activate = stub_activate;
newLadspaDescriptor->cleanup = stub_cleanup;
newLadspaDescriptor->connect_port = stub_connectPort;
newLadspaDescriptor->deactivate = stub_deactivate;
newLadspaDescriptor->instantiate = instantiate;
newLadspaDescriptor->run = stub_run;
newLadspaDescriptor->run_adding = NULL;
newLadspaDescriptor->set_run_adding_gain = NULL;
}
newDssiDescriptor->LADSPA_Plugin = newLadspaDescriptor;
newDssiDescriptor->DSSI_API_Version = 1;
newDssiDescriptor->configure = NULL;
newDssiDescriptor->get_program = stub_getProgram;
newDssiDescriptor->get_midi_controller_for_port = stub_getMidiControllerForPort;
newDssiDescriptor->select_program = stub_selectProgram;
newDssiDescriptor->run_synth = stub_runSynth;
newDssiDescriptor->run_synth_adding = NULL;
newDssiDescriptor->run_multiple_synths = NULL;
newDssiDescriptor->run_multiple_synths_adding = NULL;
}
dssiDescriptor = newDssiDescriptor;
return dssiDescriptor;
}
/**
* Converts a LADSPA / DSSI handle into a DSSIaudiooutput instance.
*
* @param instance [in]
* @return the instance
*/
DSSIaudiooutput* DSSIaudiooutput::getInstance(LADSPA_Handle instance)
{
return (DSSIaudiooutput*)(instance);
}
/**
* The private sole constructor for the DSSIaudiooutput class.
*
* Only ever called via instantiate().
* @param sampleRate [in] the sample rate to be used by the synth.
* @return
*/
DSSIaudiooutput::DSSIaudiooutput(unsigned long sampleRate)
{
this->sampleRate = sampleRate;
this->banksInited = false;
config.init();
srand(time(NULL));
denormalkillbuf=new REALTYPE [SOUND_BUFFER_SIZE];
for (int i=0;i<SOUND_BUFFER_SIZE;i++) denormalkillbuf[i]=(RND-0.5)*1e-16;
this->master = new Master();
}
/**
* The destructor for the DSSIaudiooutput class
* @return
*/
DSSIaudiooutput::~DSSIaudiooutput()
{
}
/**
* Ensures the list of bank (directories) has been initialised.
*/
void DSSIaudiooutput::initBanks(void)
{
if(!banksInited)
{
pthread_mutex_lock(&master->mutex);
master->bank.rescanforbanks();
banksInited = true;
pthread_mutex_unlock(&master->mutex);
}
}
/**
* constructor for the internally used ProgramDescriptor class
*
* @param _bank [in] bank number
* @param _program [in] program number
* @param _name [in] instrument / sample name
* @return
*/
DSSIaudiooutput::ProgramDescriptor::ProgramDescriptor(unsigned long _bank, unsigned long _program, char* _name) :
bank(_bank), program(_program), name(_name)
{
}
/**
* The map of programs available; held as a single shared statically allocated object.
*/
vector <DSSIaudiooutput::ProgramDescriptor> DSSIaudiooutput::programMap = vector<DSSIaudiooutput::ProgramDescriptor>();
/**
* Index controlling the map of banks
*/
long DSSIaudiooutput::bankNoToMap = 1;
/**
* Queries and maps the next available bank of instruments.
*
* If the program index requested to getProgram() lies beyond the banks mapped to date,
* this member function is called to map the next one.
* @return true if a new bank has been found and mapped, else false.
*/
bool DSSIaudiooutput::mapNextBank()
{
pthread_mutex_lock(&master->mutex);
Bank& bank = master->bank;
bool retval;
if(bankNoToMap >= MAX_NUM_BANKS || bank.banks[bankNoToMap].dir == NULL)
{
retval = false;
}
else
{
bank.loadbank(bank.banks[bankNoToMap].dir);
for(unsigned long instrument = 0; instrument < BANK_SIZE; instrument++)
{
char* insName = bank.getname(instrument);
if(insName != NULL && insName[0] != '\0' && insName[0] != ' ')
{
programMap.push_back(ProgramDescriptor(bankNoToMap,instrument,insName));
}
}
bankNoToMap ++;
retval = true;
}
pthread_mutex_unlock(&master->mutex);
return retval;
}

View File

@@ -1,111 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
VSTaudiooutput.h - Audio output for VST
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
*/
#ifndef VST_AUDIO_OUTPUT_H
#define VST_AUDIO_OUTPUT_H
#include <pthread.h>
#include "../globals.h"
#include "../Misc/Master.h"
#include <dssi.h>
#include <ladspa.h>
#include <vector>
class DSSIaudiooutput
{
public:
//
// Static stubs for LADSPA member functions
//
static void stub_connectPort(LADSPA_Handle instance, unsigned long port, LADSPA_Data * data);
static void stub_activate(LADSPA_Handle instance);
static void stub_run(LADSPA_Handle instance, unsigned long sample_count);
static void stub_deactivate(LADSPA_Handle Instance);
static void stub_cleanup(LADSPA_Handle instance);
//
// Static stubs for DSSI member functions
//
static const DSSI_Program_Descriptor* stub_getProgram (LADSPA_Handle instance, unsigned long Index);
static void stub_selectProgram(LADSPA_Handle instance, unsigned long bank, unsigned long program);
static int stub_getMidiControllerForPort(LADSPA_Handle instance, unsigned long port);
static void stub_runSynth(LADSPA_Handle instance, unsigned long sample_count,
snd_seq_event_t *events, unsigned long event_count);
/*
* LADSPA member functions
*/
static LADSPA_Handle instantiate(const LADSPA_Descriptor * descriptor, unsigned long s_rate);
void connectPort(unsigned long port, LADSPA_Data * data);
void activate();
void run(unsigned long sample_count);
void deactivate();
void cleanup();
static const LADSPA_Descriptor* getLadspaDescriptor(unsigned long index);
/*
* DSSI member functions
*/
const DSSI_Program_Descriptor* getProgram (unsigned long Index);
void selectProgram(unsigned long bank, unsigned long program);
int getMidiControllerForPort(unsigned long port);
void runSynth(unsigned long sample_count, snd_seq_event_t *events, unsigned long event_count);
static const DSSI_Descriptor* getDssiDescriptor(unsigned long index);
struct ProgramDescriptor
{
unsigned long bank;
unsigned long program;
string name;
ProgramDescriptor(unsigned long _bank, unsigned long _program, char* _name);
};
private:
DSSIaudiooutput(unsigned long sampleRate);
~DSSIaudiooutput();
static DSSI_Descriptor* initDssiDescriptor();
static DSSIaudiooutput* getInstance(LADSPA_Handle instance);
void initBanks();
bool mapNextBank();
LADSPA_Data *outl;
LADSPA_Data *outr;
long sampleRate;
Master* master;
static DSSI_Descriptor* dssiDescriptor;
static string bankDirNames[];
static
vector <ProgramDescriptor> programMap;
/**
* Flag controlling the list of bank directories
*/
bool banksInited;
static
long bankNoToMap;
};
#endif

View File

@@ -1,229 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
JACKaudiooutput.cpp - Audio output for JACK
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
*/
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
extern "C"
{
#include <jack/ringbuffer.h>
};
#include "JACKaudiooutput.h"
Master *jackmaster;
jack_client_t *jackclient;
jack_port_t *outport_left, *outport_right;
jack_ringbuffer_t *rb = NULL;
REALTYPE *jackoutl, *jackoutr;
int jackfinish = 0;
void *thread_blocked(void *arg);
int jackprocess(jack_nframes_t nframes, void *arg);
int jacksrate(jack_nframes_t nframes, void *arg);
void jackshutdown(void *arg);
pthread_cond_t more_data = PTHREAD_COND_INITIALIZER;
pthread_mutex_t zyn_thread_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t bthr;
bool JACKaudiooutputinit(Master *master_)
{
jackmaster = master_;
jackclient = 0;
char tmpstr[100];
jackoutl = new REALTYPE [SOUND_BUFFER_SIZE];
jackoutr = new REALTYPE [SOUND_BUFFER_SIZE];
int rbbufsize = SOUND_BUFFER_SIZE * sizeof(REALTYPE) * 2 * 2;
printf("%d\n", rbbufsize);
rb = jack_ringbuffer_create(rbbufsize);
for(int i = 0; i < rbbufsize; i++)
rb->buf[i] = 0.0;
for(int i = 0; i < 15; i++) {
if(i != 0)
snprintf(tmpstr, 100, "ZynAddSubFX_%d", i);
else
snprintf(tmpstr, 100, "ZynAddSubFX");
jackclient = jack_client_new(tmpstr);
if(jackclient != 0)
break;
}
if(jackclient == 0) {
fprintf(
stderr,
"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n");
return false;
}
fprintf(stderr,
"Internal SampleRate = %d\nJack Output SampleRate= %d\n",
SAMPLE_RATE,
jack_get_sample_rate(jackclient));
if((unsigned int)jack_get_sample_rate(jackclient) !=
(unsigned int) SAMPLE_RATE)
fprintf(stderr,
"It is recomanded that the both samplerates to be equal.\n");
jack_set_process_callback(jackclient, jackprocess, 0);
jack_set_sample_rate_callback(jackclient, jacksrate, 0);
jack_on_shutdown(jackclient, jackshutdown, 0);
outport_left = jack_port_register(jackclient,
"out_1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
outport_right = jack_port_register(jackclient,
"out_2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
if(jack_activate(jackclient)) {
fprintf(stderr, "Cannot activate jack client\n");
return false;
}
pthread_create(&bthr, NULL, thread_blocked, NULL);
/*
jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1");
jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2");
*/
return true;
}
void *thread_blocked(void *arg)
{
int datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE);
//try to get realtime
sched_param sc;
sc.sched_priority = 50;
int err = sched_setscheduler(0, SCHED_FIFO, &sc);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_mutex_lock(&zyn_thread_lock);
while(jackfinish == 0) {
while(jack_ringbuffer_write_space(rb) >= datasize) {
pthread_mutex_lock(&jackmaster->mutex);
jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,
jack_get_sample_rate(jackclient),
jackoutl,
jackoutr);
pthread_mutex_unlock(&jackmaster->mutex);
jack_ringbuffer_write(rb, (char *) jackoutl, datasize);
jack_ringbuffer_write(rb, (char *) jackoutr, datasize);
}
pthread_cond_wait(&more_data, &zyn_thread_lock);
}
pthread_mutex_unlock(&zyn_thread_lock);
return 0;
}
int jackprocess(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *outl =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_left,
nframes);
jack_default_audio_sample_t *outr =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_right,
nframes);
int datasize = nframes * sizeof(REALTYPE);
int incoming_datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE);
int data_read = 0;
if(jack_ringbuffer_read_space(rb) >= (2 * incoming_datasize)) {
if(datasize > incoming_datasize) {
data_read = 0;
while(data_read < datasize) {
jack_ringbuffer_read(rb, (char *) outl + data_read, datasize);
jack_ringbuffer_read(rb, (char *) outr + data_read, datasize);
data_read += incoming_datasize;
}
}
else
if(datasize == incoming_datasize) {
jack_ringbuffer_read(rb, (char *) outl, datasize);
jack_ringbuffer_read(rb, (char *) outr, datasize);
}
else {}
}
else { //the ringbuffer is empty or there are too small amount of samples in it
for(int i = 0; i < nframes; i++) {
outl[i] = 0.0;
outr[i] = 0.0;
}
}
/* if (jack_ringbuffer_read_space(rb)>=datasize){
jack_ringbuffer_read(rb, (char *) outl,datasize);
jack_ringbuffer_read(rb, (char *) outr,datasize);
} else {//the ringbuffer is empty or there are too small amount of samples in it
for (int i=0;i<nframes;i++){
outl[i]=0.0;outr[i]=0.0;
};
};
*/
if(pthread_mutex_trylock(&zyn_thread_lock) == 0) {
pthread_cond_signal(&more_data);
pthread_mutex_unlock(&zyn_thread_lock);
}
return 0;
}
void JACKfinish()
{
jackfinish = 1;
jack_ringbuffer_free(rb);
jack_client_close(jackclient);
usleep(100000);
delete (jackoutl);
delete (jackoutr);
}
int jacksrate(jack_nframes_t nframes, void *arg)
{
return 0;
}
void jackshutdown(void *arg)
{}

View File

@@ -1,185 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
JACKaudiooutput.cpp - Audio output for JACK
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
*/
#include <stdlib.h>
#include <jack/midiport.h>
#include "JACKaudiooutput.h"
Master *jackmaster;
jack_client_t *jackclient;
char jackname[100];
jack_port_t *outport_left, *outport_right, *midi_inport;
int jackprocess(jack_nframes_t nframes, void *arg);
int jacksrate(jack_nframes_t nframes, void *arg);
void jackshutdown(void *arg);
bool JACKaudiooutputinit(Master *master_)
{
jackmaster = master_;
jackclient = 0;
for(int i = 0; i < 15; i++) {
if(i != 0)
snprintf(jackname, 100, "ZynAddSubFX_%d", i);
else
snprintf(jackname, 100, "ZynAddSubFX");
jackclient = jack_client_new(jackname);
if(jackclient != 0)
break;
}
if(jackclient == 0) {
fprintf(
stderr,
"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n");
return false;
}
fprintf(stderr,
"Internal SampleRate = %d\nJack Output SampleRate= %d\n",
SAMPLE_RATE,
jack_get_sample_rate(jackclient));
if((unsigned int)jack_get_sample_rate(jackclient) !=
(unsigned int) SAMPLE_RATE)
fprintf(stderr,
"It is recomanded that the both samplerates to be equal.\n");
jack_set_process_callback(jackclient, jackprocess, 0);
jack_set_sample_rate_callback(jackclient, jacksrate, 0);
jack_on_shutdown(jackclient, jackshutdown, 0);
outport_left = jack_port_register(jackclient,
"out_1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
outport_right = jack_port_register(jackclient,
"out_2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
midi_inport = jack_port_register(jackclient,
"midi_input",
JACK_DEFAULT_MIDI_TYPE,
JackPortIsInput | JackPortIsTerminal,
0);
if(jack_activate(jackclient)) {
fprintf(stderr, "Cannot activate jack client\n");
return false;
}
/*
jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1");
jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2");
*/
return true;
}
int jackprocess(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *outl =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_left,
nframes);
jack_default_audio_sample_t *outr =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_right,
nframes);
if(!pthread_mutex_trylock(&jackmaster->mutex)) {
JACKhandlemidi(nframes);
jackmaster->GetAudioOutSamples(nframes, jack_get_sample_rate(
jackclient), outl, outr);
pthread_mutex_unlock(&jackmaster->mutex);
}
else {
memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes);
memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes);
}
return 0;
}
void JACKfinish()
{
jack_client_close(jackclient);
}
int jacksrate(jack_nframes_t nframes, void *arg)
{
return 0;
}
void jackshutdown(void *arg)
{}
void JACKhandlemidi(unsigned long frames)
{
// We must have the master mutex before we run this function
// XXX This is really nasty, not only do we lose the sample accuracy of
// JACK MIDI, but any accuracy at all below the buffer size
void *midi_buf = jack_port_get_buffer(midi_inport, frames);
jack_midi_event_t jack_midi_event;
jack_nframes_t event_index = 0;
unsigned char *midi_data;
unsigned char type, chan;
while(jack_midi_event_get(&jack_midi_event, midi_buf,
event_index++) == 0) {
midi_data = jack_midi_event.buffer;
type = midi_data[0] & 0xF0;
chan = midi_data[0] & 0x0F;
switch(type) {
case 0x80: /* note-off */
jackmaster->NoteOff(chan, midi_data[1]);
break;
case 0x90: /* note-on */
jackmaster->NoteOn(chan, midi_data[1], midi_data[2]);
break;
case 0xB0: /* controller */
jackmaster->SetController(chan, midi_data[1], midi_data[2]);
break;
case 0xE0: /* pitch bend */
jackmaster->SetController(chan, C_pitchwheel,
((midi_data[2] << 7) | midi_data[1]));
break;
/* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */
}
}
}
const char *JACKgetname()
{
if(jackclient != NULL)
return jackname;
return NULL;
}

View File

@@ -1,48 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
JACKaudiooutput.h - Audio output for JACK
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
*/
#ifndef JACK_AUDIO_OUTPUT_H
#define JACK_AUDIO_OUTPUT_H
#include <jack/jack.h>
#include "../globals.h"
#include "../Misc/Master.h"
#if (REALTYPE != jack_default_audio_sample_t)
#error \
"The internal sample datatype of ZynAddSubFX and the datatype of jack differs. \
In order to compile ZynAddSubFX the 'REALTYPE' and 'jack_default_audio_sample_t' must be equal. \
Set the 'REALTYPE' data type (which is defined in 'globals.h') to what is defined \
in the file types.h from jack include directory as 'jack_default_audio_sample_t' (as float or double)."
#endif
bool JACKaudiooutputinit(Master *master_);
void JACKfinish();
void JACKhandlemidi(unsigned long frames);
const char *JACKgetname();
#endif

View File

@@ -1,128 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
OSSaudiooutput.cpp - Audio output 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
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 <fcntl.h>
#include <sys/soundcard.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <iostream>
#include "OSSaudiooutput.h"
#include "../Misc/Util.h"
#include "../globals.h"
using namespace std;
OSSaudiooutput::OSSaudiooutput()
{
int i;
int snd_bitsize = 16;
snd_fragment = 0x00080009; //fragment size (?)
snd_stereo = 1; //stereo
snd_format = AFMT_S16_LE;
snd_samplerate = SAMPLE_RATE;
playing_until.tv_sec = 0;
playing_until.tv_usec = 0;
smps = new short int[SOUND_BUFFER_SIZE * 2];
for(i = 0; i < SOUND_BUFFER_SIZE * 2; i++)
smps[i] = 0;
snd_handle = open(config.cfg.LinuxOSSWaveOutDev, O_WRONLY, 0);
if(snd_handle == -1) {
cerr << "ERROR - I can't open the ";
cerr << config.cfg.LinuxOSSWaveOutDev << '.' << endl;
return;
}
ioctl(snd_handle, SNDCTL_DSP_RESET, NULL);
ioctl(snd_handle, SNDCTL_DSP_SETFMT, &snd_format);
ioctl(snd_handle, SNDCTL_DSP_STEREO, &snd_stereo);
ioctl(snd_handle, SNDCTL_DSP_SPEED, &snd_samplerate);
ioctl(snd_handle, SNDCTL_DSP_SAMPLESIZE, &snd_bitsize);
ioctl(snd_handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment);
}
/*
* Output the samples to the soundcard
* The samples are bigger than -1.0 and smaller 1.0
*/
void OSSaudiooutput::OSSout(REALTYPE *smp_left, REALTYPE *smp_right)
{
int i;
REALTYPE l, r;
if(snd_handle < 0) { //output could not be opened
struct timeval now;
int remaining;
gettimeofday(&now, NULL);
if((playing_until.tv_usec == 0) && (playing_until.tv_sec == 0)) {
playing_until.tv_usec = now.tv_usec;
playing_until.tv_sec = now.tv_sec;
}
else {
remaining = (playing_until.tv_usec - now.tv_usec)
+ (playing_until.tv_sec - now.tv_sec) * 1000000;
if(remaining > 10000) //Don't sleep() less than 10ms.
//This will add latency...
usleep(remaining - 10000);
if(remaining < 0)
cerr << "WARNING - too late" << endl;
}
playing_until.tv_usec += SOUND_BUFFER_SIZE * 1000000 / SAMPLE_RATE;
if(remaining < 0)
playing_until.tv_usec -= remaining;
playing_until.tv_sec += playing_until.tv_usec / 1000000;
playing_until.tv_usec %= 1000000;
return;
}
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
l = smp_left[i];
r = smp_right[i];
if(l < -1.0)
l = -1.0;
else
if(l > 1.0)
l = 1.0;
if(r < -1.0)
r = -1.0;
else
if(r > 1.0)
r = 1.0;
smps[i * 2] = (short int) (l * 32767.0);
smps[i * 2 + 1] = (short int) (r * 32767.0);
}
write(snd_handle, smps, SOUND_BUFFER_SIZE * 4); // *2 because is 16 bit, again * 2 because is stereo
}
OSSaudiooutput::~OSSaudiooutput()
{
close(snd_handle);
delete [] smps;
}

View File

@@ -1,50 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
OSSaudiooutput.h - Audio output 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
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 OSS_AUDIO_OUTPUT_H
#define OSS_AUDIO_OUTPUT_H
#include <sys/time.h>
#include "../globals.h"
class OSSaudiooutput
{
public:
OSSaudiooutput();
~OSSaudiooutput();
//the out is [-1.0 .. 1.0]
/* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */
void OSSout(REALTYPE *smp_left, REALTYPE *smp_right);
private:
int snd_handle;
int snd_fragment;
int snd_stereo;
int snd_format;
int snd_samplerate;
struct timeval playing_until;
short int *smps; //Samples to be sent to soundcard
};
#endif

View File

@@ -1,80 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
PAaudiooutput.cpp - Audio output for PortAudio
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
*/
#include "PAaudiooutput.h"
Master *PAmaster;
PaStream *stream;
REALTYPE *outl, *outr;
int PAprocess(void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
PaTimestamp outTime, void *userData)
{
if(framesPerBuffer != SOUND_BUFFER_SIZE) {
fprintf(
stderr,
"Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer");
fprintf(stderr, "%d %d\n", framesPerBuffer, SOUND_BUFFER_SIZE);
}
pthread_mutex_lock(&PAmaster->mutex);
PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE, SAMPLE_RATE, outl, outr);
pthread_mutex_unlock(&PAmaster->mutex);
float *out = (float *)outputBuffer;
for(int i = 0; i < framesPerBuffer; i++) {
if(i >= SOUND_BUFFER_SIZE)
break; //this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE
out[i * 2] = outl[i];
out[i * 2 + 1] = outr[i];
}
return 0;
}
void PAaudiooutputinit(Master *master_)
{
PAmaster = master_;
outl = new REALTYPE [SOUND_BUFFER_SIZE];
outr = new REALTYPE [SOUND_BUFFER_SIZE];
Pa_Initialize();
Pa_OpenDefaultStream(&stream,
0,
2,
paFloat32,
SAMPLE_RATE,
SOUND_BUFFER_SIZE,
0,
PAprocess,
NULL);
Pa_StartStream(stream);
}
void PAfinish()
{
Pa_StopStream(stream);
delete (outl);
delete (outr);
}

View File

@@ -1,34 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
PAaudiooutput.h - Audio output for PortAudio
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
*/
#ifndef PA_AUDIO_OUTPUT_H
#define PA_AUDIO_OUTPUT_H
#include <portaudio.h>
#include "../globals.h"
#include "../Misc/Master.h"
void PAaudiooutputinit(Master *master_);
void PAfinish();
#endif

View File

@@ -1,113 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Recorder.cpp - Records sound to a 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 <sys/stat.h>
#include "Recorder.h"
Recorder::Recorder()
{
recordbuf_16bit = new short int [SOUND_BUFFER_SIZE * 2];
status = 0;
notetrigger = 0;
for(int i = 0; i < SOUND_BUFFER_SIZE * 2; i++)
recordbuf_16bit[i] = 0;
}
Recorder::~Recorder()
{
if(recording() == 1)
stop();
delete [] recordbuf_16bit;
}
int Recorder::preparefile(std::string filename_, int overwrite)
{
if(!overwrite) {
struct stat fileinfo;
int statr;
statr = stat(filename_.c_str(), &fileinfo);
if(statr == 0) //file exists
return 1;
}
if(!wav.newfile(filename_, SAMPLE_RATE, 2))
return 2;
status = 1; //ready
return 0;
}
void Recorder::start()
{
notetrigger = 0;
status = 2; //recording
}
void Recorder::stop()
{
wav.close();
status = 0;
}
void Recorder::pause()
{
status = 0;
}
int Recorder::recording()
{
if((status == 2) && (notetrigger != 0))
return 1;
else
return 0;
}
void Recorder::recordbuffer(REALTYPE *outl, REALTYPE *outr)
{
int tmp;
if(status != 2)
return;
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
tmp = (int)(outl[i] * 32767.0);
if(tmp < -32768)
tmp = -32768;
if(tmp > 32767)
tmp = 32767;
recordbuf_16bit[i * 2] = tmp;
tmp = (int)(outr[i] * 32767.0);
if(tmp < -32768)
tmp = -32768;
if(tmp > 32767)
tmp = 32767;
recordbuf_16bit[i * 2 + 1] = tmp;
}
wav.write_stereo_samples(SOUND_BUFFER_SIZE, recordbuf_16bit);
}
void Recorder::triggernow()
{
if(status == 2)
notetrigger = 1;
}

View File

@@ -1,57 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Recorder.h - Records sound to a 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
*/
#ifndef RECORDER_H
#define RECORDER_H
#include <string>
#include "../globals.h"
#include "WAVaudiooutput.h"
/**Records sound to a file*/
class Recorder
{
public:
Recorder();
~Recorder();
int preparefile(std::string filename_, int overwrite); //returns 1 if the file exists
void start();
void stop();
void pause();
int recording();
void triggernow();
void recordbuffer(REALTYPE *outl, REALTYPE *outr);
/** Status:
* 0 - not ready(no file selected),
* 1 - ready
* 2 - recording */
int status;
private:
WAVaudiooutput wav;
short int *recordbuf_16bit;
int notetrigger;
};
#endif

View File

@@ -1,68 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
VSTaudiooutput.cpp - Audio output for VST
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
*/
#include <string.h>
#include "VSTaudiooutput.h"
//the constructor and the destructor are defined in main.cpp
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();
}

View File

@@ -1,60 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
VSTaudiooutput.h - Audio output for VST
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
*/
#ifndef VST_AUDIO_OUTPUT_H
#define VST_AUDIO_OUTPUT_H
#include <pthread.h>
#include "../globals.h"
#include "../Misc/Master.h"
#include "../UI/MasterUI.h"
#include "../../../vstsdk2/source/common/audioeffectx.h"
class VSTSynth:public AudioEffectX
{
public:
VSTSynth(audioMasterCallback audioMaster);
~VSTSynth();
virtual void process(float **inputs, float **outputs, long sampleframes);
virtual void processReplacing(float **inputs,
float **outputs,
long sampleframes);
virtual long processEvents(VstEvents *events); //this is used for Midi input
virtual long int canDo(char *txt);
virtual bool getVendorString(char *txt);
virtual bool getProductString(char *txt);
virtual void resume();
virtual long getChunk(void **data, bool isPreset = false);
virtual long setChunk(void *data, long size, bool isPreset = false);
MasterUI *ui;
int Pexitprogram;
Master *vmaster;
pthread_t thr;
};
#endif

View File

@@ -1,101 +0,0 @@
/*
Copyright (C) 2006 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) 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 <stdlib.h>
#include "WAVaudiooutput.h"
using namespace std;
WAVaudiooutput::WAVaudiooutput()
{
file = NULL;
sampleswritten = 0;
samplerate = 44100;
}
WAVaudiooutput::~WAVaudiooutput()
{
close();
}
bool WAVaudiooutput::newfile(string filename, int samplerate, int channels)
{
/**\todo Move this into the Constructor*/
close(); //inchide un posibil fisier existent
file = fopen(filename.c_str(), "w");
if(!file)
return false;
this->samplerate = samplerate;
this->channels = channels;
sampleswritten = 0;
char tmp[44];
fwrite(tmp, 1, 44, file);
return true;
}
void WAVaudiooutput::close()
{
if(file) {
unsigned int chunksize;
rewind(file);
fwrite("RIFF", 4, 1, file);
chunksize = sampleswritten * 4 + 36;
fwrite(&chunksize, 4, 1, file);
fwrite("WAVEfmt ", 8, 1, file);
chunksize = 16;
fwrite(&chunksize, 4, 1, file);
unsigned short int formattag = 1; //uncompresed wave
fwrite(&formattag, 2, 1, file);
unsigned short int nchannels = channels; //stereo
fwrite(&nchannels, 2, 1, file);
unsigned int samplerate_ = samplerate; //samplerate
fwrite(&samplerate_, 4, 1, file);
unsigned int bytespersec = samplerate * 2 * channels; //bytes/sec
fwrite(&bytespersec, 4, 1, file);
unsigned short int blockalign = 2 * channels; //2 channels * 16 bits/8
fwrite(&blockalign, 2, 1, file);
unsigned short int bitspersample = 16;
fwrite(&bitspersample, 2, 1, file);
fwrite("data", 4, 1, file);
chunksize = sampleswritten * blockalign;
fwrite(&chunksize, 4, 1, file);
fclose(file);
file = NULL;
}
}
void WAVaudiooutput::write_stereo_samples(int nsmps, short int *smps)
{
if(!file)
return;
fwrite(smps, nsmps, 4, file);
sampleswritten += nsmps;
}
void WAVaudiooutput::write_mono_samples(int nsmps, short int *smps)
{
if(!file)
return;
fwrite(smps, nsmps, 2, file);
sampleswritten += nsmps;
}

View File

@@ -1,43 +0,0 @@
/*
Copyright (C) 2008 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) 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 WAVOUTPUT_H
#define WAVOUTPUT_H
#include <string>
class WAVaudiooutput
{
public:
WAVaudiooutput();
~WAVaudiooutput();
bool newfile(std::string filename, int samplerate, int channels);
void close();
void write_mono_samples(int nsmps, short int *smps);
void write_stereo_samples(int nsmps, short int *smps);
private:
int sampleswritten;
int samplerate;
int channels;
FILE *file;
};
#endif

View File

@@ -1,840 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
ADnoteParameters.cpp - Parameters for ADnote (ADsynth)
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 <math.h>
#include "ADnoteParameters.h"
int ADnote_unison_sizes[] =
{1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0};
ADnoteParameters::ADnoteParameters(FFTwrapper *fft_)
:PresetsArray()
{
setpresettype("Padsyth");
fft = fft_;
GlobalPar.FreqEnvelope = new EnvelopeParams(0, 0);
GlobalPar.FreqEnvelope->ASRinit(64, 50, 64, 60);
GlobalPar.FreqLfo = new LFOParams(70, 0, 64, 0, 0, 0, 0, 0);
GlobalPar.AmpEnvelope = new EnvelopeParams(64, 1);
GlobalPar.AmpEnvelope->ADSRinit_dB(0, 40, 127, 25);
GlobalPar.AmpLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 1);
GlobalPar.GlobalFilter = new FilterParams(2, 94, 40);
GlobalPar.FilterEnvelope = new EnvelopeParams(0, 1);
GlobalPar.FilterEnvelope->ADSRinit_filter(64, 40, 64, 70, 60, 64);
GlobalPar.FilterLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 2);
GlobalPar.Reson = new Resonance();
for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++)
EnableVoice(nvoice);
defaults();
}
void ADnoteParameters::defaults()
{
//Default Parameters
/* Frequency Global Parameters */
GlobalPar.PStereo = 1; //stereo
GlobalPar.PDetune = 8192; //zero
GlobalPar.PCoarseDetune = 0;
GlobalPar.PDetuneType = 1;
GlobalPar.FreqEnvelope->defaults();
GlobalPar.FreqLfo->defaults();
GlobalPar.PBandwidth = 64;
/* Amplitude Global Parameters */
GlobalPar.PVolume = 90;
GlobalPar.PPanning = 64; //center
GlobalPar.PAmpVelocityScaleFunction = 64;
GlobalPar.AmpEnvelope->defaults();
GlobalPar.AmpLfo->defaults();
GlobalPar.PPunchStrength = 0;
GlobalPar.PPunchTime = 60;
GlobalPar.PPunchStretch = 64;
GlobalPar.PPunchVelocitySensing = 72;
GlobalPar.Hrandgrouping = 0;
/* Filter Global Parameters*/
GlobalPar.PFilterVelocityScale = 64;
GlobalPar.PFilterVelocityScaleFunction = 64;
GlobalPar.GlobalFilter->defaults();
GlobalPar.FilterEnvelope->defaults();
GlobalPar.FilterLfo->defaults();
GlobalPar.Reson->defaults();
for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++)
defaults(nvoice);
;
VoicePar[0].Enabled = 1;
}
/*
* Defaults a voice
*/
void ADnoteParameters::defaults(int n)
{
int nvoice = n;
VoicePar[nvoice].Enabled = 0;
VoicePar[nvoice].Unison_size = 1;
VoicePar[nvoice].Unison_frequency_spread = 60;
VoicePar[nvoice].Unison_stereo_spread = 64;
VoicePar[nvoice].Unison_vibratto = 64;
VoicePar[nvoice].Unison_vibratto_speed = 64;
VoicePar[nvoice].Unison_invert_phase = 0;
VoicePar[nvoice].Type = 0;
VoicePar[nvoice].Pfixedfreq = 0;
VoicePar[nvoice].PfixedfreqET = 0;
VoicePar[nvoice].Presonance = 1;
VoicePar[nvoice].Pfilterbypass = 0;
VoicePar[nvoice].Pextoscil = -1;
VoicePar[nvoice].PextFMoscil = -1;
VoicePar[nvoice].Poscilphase = 64;
VoicePar[nvoice].PFMoscilphase = 64;
VoicePar[nvoice].PDelay = 0;
VoicePar[nvoice].PVolume = 100;
VoicePar[nvoice].PVolumeminus = 0;
VoicePar[nvoice].PPanning = 64; //center
VoicePar[nvoice].PDetune = 8192; //8192=0
VoicePar[nvoice].PCoarseDetune = 0;
VoicePar[nvoice].PDetuneType = 0;
VoicePar[nvoice].PFreqLfoEnabled = 0;
VoicePar[nvoice].PFreqEnvelopeEnabled = 0;
VoicePar[nvoice].PAmpEnvelopeEnabled = 0;
VoicePar[nvoice].PAmpLfoEnabled = 0;
VoicePar[nvoice].PAmpVelocityScaleFunction = 127;
VoicePar[nvoice].PFilterEnabled = 0;
VoicePar[nvoice].PFilterEnvelopeEnabled = 0;
VoicePar[nvoice].PFilterLfoEnabled = 0;
VoicePar[nvoice].PFMEnabled = 0;
//I use the internal oscillator (-1)
VoicePar[nvoice].PFMVoice = -1;
VoicePar[nvoice].PFMVolume = 90;
VoicePar[nvoice].PFMVolumeDamp = 64;
VoicePar[nvoice].PFMDetune = 8192;
VoicePar[nvoice].PFMCoarseDetune = 0;
VoicePar[nvoice].PFMDetuneType = 0;
VoicePar[nvoice].PFMFreqEnvelopeEnabled = 0;
VoicePar[nvoice].PFMAmpEnvelopeEnabled = 0;
VoicePar[nvoice].PFMVelocityScaleFunction = 64;
VoicePar[nvoice].OscilSmp->defaults();
VoicePar[nvoice].FMSmp->defaults();
VoicePar[nvoice].AmpEnvelope->defaults();
VoicePar[nvoice].AmpLfo->defaults();
VoicePar[nvoice].FreqEnvelope->defaults();
VoicePar[nvoice].FreqLfo->defaults();
VoicePar[nvoice].VoiceFilter->defaults();
VoicePar[nvoice].FilterEnvelope->defaults();
VoicePar[nvoice].FilterLfo->defaults();
VoicePar[nvoice].FMFreqEnvelope->defaults();
VoicePar[nvoice].FMAmpEnvelope->defaults();
}
/*
* Init the voice parameters
*/
void ADnoteParameters::EnableVoice(int nvoice)
{
VoicePar[nvoice].OscilSmp = new OscilGen(fft, GlobalPar.Reson);
VoicePar[nvoice].FMSmp = new OscilGen(fft, NULL);
VoicePar[nvoice].AmpEnvelope = new EnvelopeParams(64, 1);
VoicePar[nvoice].AmpEnvelope->ADSRinit_dB(0, 100, 127, 100);
VoicePar[nvoice].AmpLfo = new LFOParams(90, 32, 64, 0, 0, 30, 0, 1);
VoicePar[nvoice].FreqEnvelope = new EnvelopeParams(0, 0);
VoicePar[nvoice].FreqEnvelope->ASRinit(30, 40, 64, 60);
VoicePar[nvoice].FreqLfo = new LFOParams(50, 40, 0, 0, 0, 0, 0, 0);
VoicePar[nvoice].VoiceFilter = new FilterParams(2, 50, 60);
VoicePar[nvoice].FilterEnvelope = new EnvelopeParams(0, 0);
VoicePar[nvoice].FilterEnvelope->ADSRinit_filter(90, 70, 40, 70, 10, 40);
VoicePar[nvoice].FilterLfo = new LFOParams(50, 20, 64, 0, 0, 0, 0, 2);
VoicePar[nvoice].FMFreqEnvelope = new EnvelopeParams(0, 0);
VoicePar[nvoice].FMFreqEnvelope->ASRinit(20, 90, 40, 80);
VoicePar[nvoice].FMAmpEnvelope = new EnvelopeParams(64, 1);
VoicePar[nvoice].FMAmpEnvelope->ADSRinit(80, 90, 127, 100);
}
/*
* Get the Multiplier of the fine detunes of the voices
*/
REALTYPE ADnoteParameters::getBandwidthDetuneMultiplier()
{
REALTYPE bw = (GlobalPar.PBandwidth - 64.0) / 64.0;
bw = pow(2.0, bw * pow(fabs(bw), 0.2) * 5.0);
return bw;
}
/*
* Get the unison spread in cents for a voice
*/
REALTYPE ADnoteParameters::getUnisonFrequencySpreadCents(int nvoice) {
REALTYPE unison_spread = VoicePar[nvoice].Unison_frequency_spread / 127.0;
unison_spread = pow(unison_spread * 2.0, 2.0) * 50.0; //cents
return unison_spread;
}
/*
* Kill the voice
*/
void ADnoteParameters::KillVoice(int nvoice)
{
delete (VoicePar[nvoice].OscilSmp);
delete (VoicePar[nvoice].FMSmp);
delete (VoicePar[nvoice].AmpEnvelope);
delete (VoicePar[nvoice].AmpLfo);
delete (VoicePar[nvoice].FreqEnvelope);
delete (VoicePar[nvoice].FreqLfo);
delete (VoicePar[nvoice].VoiceFilter);
delete (VoicePar[nvoice].FilterEnvelope);
delete (VoicePar[nvoice].FilterLfo);
delete (VoicePar[nvoice].FMFreqEnvelope);
delete (VoicePar[nvoice].FMAmpEnvelope);
}
ADnoteParameters::~ADnoteParameters()
{
delete (GlobalPar.FreqEnvelope);
delete (GlobalPar.FreqLfo);
delete (GlobalPar.AmpEnvelope);
delete (GlobalPar.AmpLfo);
delete (GlobalPar.GlobalFilter);
delete (GlobalPar.FilterEnvelope);
delete (GlobalPar.FilterLfo);
delete (GlobalPar.Reson);
for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++)
KillVoice(nvoice);
;
}
int ADnoteParameters::get_unison_size_index(int nvoice) {
int index = 0;
if(nvoice >= NUM_VOICES)
return 0;
int unison = VoicePar[nvoice].Unison_size;
while(1) {
if(ADnote_unison_sizes[index] >= unison)
return index;
;
if(ADnote_unison_sizes[index] == 0)
return index - 1;
;
index++;
}
return 0;
}
void ADnoteParameters::set_unison_size_index(int nvoice, int index) {
int unison = 1;
for(int i = 0; i <= index; i++) {
unison = ADnote_unison_sizes[i];
if(unison == 0) {
unison = ADnote_unison_sizes[i - 1];
break;
}
}
VoicePar[nvoice].Unison_size = unison;
}
void ADnoteParameters::add2XMLsection(XMLwrapper *xml, int n)
{
int nvoice = n;
if(nvoice >= NUM_VOICES)
return;
int oscilused = 0, fmoscilused = 0; //if the oscil or fmoscil are used by another voice
for(int i = 0; i < NUM_VOICES; i++) {
if(VoicePar[i].Pextoscil == nvoice)
oscilused = 1;
if(VoicePar[i].PextFMoscil == nvoice)
fmoscilused = 1;
}
xml->addparbool("enabled", VoicePar[nvoice].Enabled);
if(((VoicePar[nvoice].Enabled == 0) && (oscilused == 0)
&& (fmoscilused == 0)) && (xml->minimal))
return;
xml->addpar("type", VoicePar[nvoice].Type);
xml->addpar("unison_size", VoicePar[nvoice].Unison_size);
xml->addpar("unison_frequency_spread",
VoicePar[nvoice].Unison_frequency_spread);
xml->addpar("unison_stereo_spread", VoicePar[nvoice].Unison_stereo_spread);
xml->addpar("unison_vibratto", VoicePar[nvoice].Unison_vibratto);
xml->addpar("unison_vibratto_speed", VoicePar[nvoice].Unison_vibratto_speed);
xml->addpar("unison_invert_phase", VoicePar[nvoice].Unison_invert_phase);
xml->addpar("delay", VoicePar[nvoice].PDelay);
xml->addparbool("resonance", VoicePar[nvoice].Presonance);
xml->addpar("ext_oscil", VoicePar[nvoice].Pextoscil);
xml->addpar("ext_fm_oscil", VoicePar[nvoice].PextFMoscil);
xml->addpar("oscil_phase", VoicePar[nvoice].Poscilphase);
xml->addpar("oscil_fm_phase", VoicePar[nvoice].PFMoscilphase);
xml->addparbool("filter_enabled", VoicePar[nvoice].PFilterEnabled);
xml->addparbool("filter_bypass", VoicePar[nvoice].Pfilterbypass);
xml->addpar("fm_enabled", VoicePar[nvoice].PFMEnabled);
xml->beginbranch("OSCIL");
VoicePar[nvoice].OscilSmp->add2XML(xml);
xml->endbranch();
xml->beginbranch("AMPLITUDE_PARAMETERS");
xml->addpar("panning", VoicePar[nvoice].PPanning);
xml->addpar("volume", VoicePar[nvoice].PVolume);
xml->addparbool("volume_minus", VoicePar[nvoice].PVolumeminus);
xml->addpar("velocity_sensing", VoicePar[nvoice].PAmpVelocityScaleFunction);
xml->addparbool("amp_envelope_enabled",
VoicePar[nvoice].PAmpEnvelopeEnabled);
if((VoicePar[nvoice].PAmpEnvelopeEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("AMPLITUDE_ENVELOPE");
VoicePar[nvoice].AmpEnvelope->add2XML(xml);
xml->endbranch();
}
xml->addparbool("amp_lfo_enabled", VoicePar[nvoice].PAmpLfoEnabled);
if((VoicePar[nvoice].PAmpLfoEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("AMPLITUDE_LFO");
VoicePar[nvoice].AmpLfo->add2XML(xml);
xml->endbranch();
}
xml->endbranch();
xml->beginbranch("FREQUENCY_PARAMETERS");
xml->addparbool("fixed_freq", VoicePar[nvoice].Pfixedfreq);
xml->addpar("fixed_freq_et", VoicePar[nvoice].PfixedfreqET);
xml->addpar("detune", VoicePar[nvoice].PDetune);
xml->addpar("coarse_detune", VoicePar[nvoice].PCoarseDetune);
xml->addpar("detune_type", VoicePar[nvoice].PDetuneType);
xml->addparbool("freq_envelope_enabled",
VoicePar[nvoice].PFreqEnvelopeEnabled);
if((VoicePar[nvoice].PFreqEnvelopeEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("FREQUENCY_ENVELOPE");
VoicePar[nvoice].FreqEnvelope->add2XML(xml);
xml->endbranch();
}
xml->addparbool("freq_lfo_enabled", VoicePar[nvoice].PFreqLfoEnabled);
if((VoicePar[nvoice].PFreqLfoEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("FREQUENCY_LFO");
VoicePar[nvoice].FreqLfo->add2XML(xml);
xml->endbranch();
}
xml->endbranch();
if((VoicePar[nvoice].PFilterEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("FILTER_PARAMETERS");
xml->beginbranch("FILTER");
VoicePar[nvoice].VoiceFilter->add2XML(xml);
xml->endbranch();
xml->addparbool("filter_envelope_enabled",
VoicePar[nvoice].PFilterEnvelopeEnabled);
if((VoicePar[nvoice].PFilterEnvelopeEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("FILTER_ENVELOPE");
VoicePar[nvoice].FilterEnvelope->add2XML(xml);
xml->endbranch();
}
xml->addparbool("filter_lfo_enabled",
VoicePar[nvoice].PFilterLfoEnabled);
if((VoicePar[nvoice].PFilterLfoEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("FILTER_LFO");
VoicePar[nvoice].FilterLfo->add2XML(xml);
xml->endbranch();
}
xml->endbranch();
}
if((VoicePar[nvoice].PFMEnabled != 0) || (fmoscilused != 0)
|| (!xml->minimal)) {
xml->beginbranch("FM_PARAMETERS");
xml->addpar("input_voice", VoicePar[nvoice].PFMVoice);
xml->addpar("volume", VoicePar[nvoice].PFMVolume);
xml->addpar("volume_damp", VoicePar[nvoice].PFMVolumeDamp);
xml->addpar("velocity_sensing",
VoicePar[nvoice].PFMVelocityScaleFunction);
xml->addparbool("amp_envelope_enabled",
VoicePar[nvoice].PFMAmpEnvelopeEnabled);
if((VoicePar[nvoice].PFMAmpEnvelopeEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("AMPLITUDE_ENVELOPE");
VoicePar[nvoice].FMAmpEnvelope->add2XML(xml);
xml->endbranch();
}
xml->beginbranch("MODULATOR");
xml->addpar("detune", VoicePar[nvoice].PFMDetune);
xml->addpar("coarse_detune", VoicePar[nvoice].PFMCoarseDetune);
xml->addpar("detune_type", VoicePar[nvoice].PFMDetuneType);
xml->addparbool("freq_envelope_enabled",
VoicePar[nvoice].PFMFreqEnvelopeEnabled);
if((VoicePar[nvoice].PFMFreqEnvelopeEnabled != 0) || (!xml->minimal)) {
xml->beginbranch("FREQUENCY_ENVELOPE");
VoicePar[nvoice].FMFreqEnvelope->add2XML(xml);
xml->endbranch();
}
xml->beginbranch("OSCIL");
VoicePar[nvoice].FMSmp->add2XML(xml);
xml->endbranch();
xml->endbranch();
xml->endbranch();
}
}
void ADnoteParameters::add2XML(XMLwrapper *xml)
{
xml->addparbool("stereo", GlobalPar.PStereo);
xml->beginbranch("AMPLITUDE_PARAMETERS");
xml->addpar("volume", GlobalPar.PVolume);
xml->addpar("panning", GlobalPar.PPanning);
xml->addpar("velocity_sensing", GlobalPar.PAmpVelocityScaleFunction);
xml->addpar("punch_strength", GlobalPar.PPunchStrength);
xml->addpar("punch_time", GlobalPar.PPunchTime);
xml->addpar("punch_stretch", GlobalPar.PPunchStretch);
xml->addpar("punch_velocity_sensing", GlobalPar.PPunchVelocitySensing);
xml->addpar("harmonic_randomness_grouping", GlobalPar.Hrandgrouping);
xml->beginbranch("AMPLITUDE_ENVELOPE");
GlobalPar.AmpEnvelope->add2XML(xml);
xml->endbranch();
xml->beginbranch("AMPLITUDE_LFO");
GlobalPar.AmpLfo->add2XML(xml);
xml->endbranch();
xml->endbranch();
xml->beginbranch("FREQUENCY_PARAMETERS");
xml->addpar("detune", GlobalPar.PDetune);
xml->addpar("coarse_detune", GlobalPar.PCoarseDetune);
xml->addpar("detune_type", GlobalPar.PDetuneType);
xml->addpar("bandwidth", GlobalPar.PBandwidth);
xml->beginbranch("FREQUENCY_ENVELOPE");
GlobalPar.FreqEnvelope->add2XML(xml);
xml->endbranch();
xml->beginbranch("FREQUENCY_LFO");
GlobalPar.FreqLfo->add2XML(xml);
xml->endbranch();
xml->endbranch();
xml->beginbranch("FILTER_PARAMETERS");
xml->addpar("velocity_sensing_amplitude", GlobalPar.PFilterVelocityScale);
xml->addpar("velocity_sensing", GlobalPar.PFilterVelocityScaleFunction);
xml->beginbranch("FILTER");
GlobalPar.GlobalFilter->add2XML(xml);
xml->endbranch();
xml->beginbranch("FILTER_ENVELOPE");
GlobalPar.FilterEnvelope->add2XML(xml);
xml->endbranch();
xml->beginbranch("FILTER_LFO");
GlobalPar.FilterLfo->add2XML(xml);
xml->endbranch();
xml->endbranch();
xml->beginbranch("RESONANCE");
GlobalPar.Reson->add2XML(xml);
xml->endbranch();
for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) {
xml->beginbranch("VOICE", nvoice);
add2XMLsection(xml, nvoice);
xml->endbranch();
}
}
void ADnoteParameters::getfromXML(XMLwrapper *xml)
{
GlobalPar.PStereo = xml->getparbool("stereo", GlobalPar.PStereo);
if(xml->enterbranch("AMPLITUDE_PARAMETERS")) {
GlobalPar.PVolume = xml->getpar127("volume", GlobalPar.PVolume);
GlobalPar.PPanning = xml->getpar127("panning", GlobalPar.PPanning);
GlobalPar.PAmpVelocityScaleFunction = xml->getpar127(
"velocity_sensing",
GlobalPar.
PAmpVelocityScaleFunction);
GlobalPar.PPunchStrength = xml->getpar127("punch_strength",
GlobalPar.PPunchStrength);
GlobalPar.PPunchTime = xml->getpar127("punch_time",
GlobalPar.PPunchTime);
GlobalPar.PPunchStretch = xml->getpar127("punch_stretch",
GlobalPar.PPunchStretch);
GlobalPar.PPunchVelocitySensing = xml->getpar127(
"punch_velocity_sensing",
GlobalPar.PPunchVelocitySensing);
GlobalPar.Hrandgrouping = xml->getpar127(
"harmonic_randomness_grouping",
GlobalPar.Hrandgrouping);
if(xml->enterbranch("AMPLITUDE_ENVELOPE")) {
GlobalPar.AmpEnvelope->getfromXML(xml);
xml->exitbranch();
}
if(xml->enterbranch("AMPLITUDE_LFO")) {
GlobalPar.AmpLfo->getfromXML(xml);
xml->exitbranch();
}
xml->exitbranch();
}
if(xml->enterbranch("FREQUENCY_PARAMETERS")) {
GlobalPar.PDetune = xml->getpar("detune",
GlobalPar.PDetune,
0,
16383);
GlobalPar.PCoarseDetune = xml->getpar("coarse_detune",
GlobalPar.PCoarseDetune,
0,
16383);
GlobalPar.PDetuneType = xml->getpar127("detune_type",
GlobalPar.PDetuneType);
GlobalPar.PBandwidth = xml->getpar127("bandwidth",
GlobalPar.PBandwidth);
xml->enterbranch("FREQUENCY_ENVELOPE");
GlobalPar.FreqEnvelope->getfromXML(xml);
xml->exitbranch();
xml->enterbranch("FREQUENCY_LFO");
GlobalPar.FreqLfo->getfromXML(xml);
xml->exitbranch();
xml->exitbranch();
}
if(xml->enterbranch("FILTER_PARAMETERS")) {
GlobalPar.PFilterVelocityScale = xml->getpar127(
"velocity_sensing_amplitude",
GlobalPar.PFilterVelocityScale);
GlobalPar.PFilterVelocityScaleFunction = xml->getpar127(
"velocity_sensing",
GlobalPar.PFilterVelocityScaleFunction);
xml->enterbranch("FILTER");
GlobalPar.GlobalFilter->getfromXML(xml);
xml->exitbranch();
xml->enterbranch("FILTER_ENVELOPE");
GlobalPar.FilterEnvelope->getfromXML(xml);
xml->exitbranch();
xml->enterbranch("FILTER_LFO");
GlobalPar.FilterLfo->getfromXML(xml);
xml->exitbranch();
xml->exitbranch();
}
if(xml->enterbranch("RESONANCE")) {
GlobalPar.Reson->getfromXML(xml);
xml->exitbranch();
}
for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) {
VoicePar[nvoice].Enabled = 0;
if(xml->enterbranch("VOICE", nvoice) == 0)
continue;
getfromXMLsection(xml, nvoice);
xml->exitbranch();
}
}
void ADnoteParameters::getfromXMLsection(XMLwrapper *xml, int n)
{
int nvoice = n;
if(nvoice >= NUM_VOICES)
return;
VoicePar[nvoice].Enabled = xml->getparbool("enabled", 0);
VoicePar[nvoice].Unison_size =
xml->getpar127("unison_size", VoicePar[nvoice].Unison_size);
VoicePar[nvoice].Unison_frequency_spread = xml->getpar127(
"unison_frequency_spread",
VoicePar[nvoice].Unison_frequency_spread);
VoicePar[nvoice].Unison_stereo_spread = xml->getpar127(
"unison_stereo_spread",
VoicePar[nvoice].Unison_stereo_spread);
VoicePar[nvoice].Unison_vibratto = xml->getpar127(
"unison_vibratto",
VoicePar[nvoice].
Unison_vibratto);
VoicePar[nvoice].Unison_vibratto_speed = xml->getpar127(
"unison_vibratto_speed",
VoicePar[nvoice].Unison_vibratto_speed);
VoicePar[nvoice].Unison_invert_phase = xml->getpar127(
"unison_invert_phase",
VoicePar[nvoice].Unison_invert_phase);
VoicePar[nvoice].Type = xml->getpar127("type",
VoicePar[nvoice].Type);
VoicePar[nvoice].PDelay = xml->getpar127("delay",
VoicePar[nvoice].PDelay);
VoicePar[nvoice].Presonance =
xml->getparbool("resonance", VoicePar[nvoice].Presonance);
VoicePar[nvoice].Pextoscil = xml->getpar("ext_oscil",
-1,
-1,
nvoice - 1);
VoicePar[nvoice].PextFMoscil = xml->getpar("ext_fm_oscil",
-1,
-1,
nvoice - 1);
VoicePar[nvoice].Poscilphase =
xml->getpar127("oscil_phase", VoicePar[nvoice].Poscilphase);
VoicePar[nvoice].PFMoscilphase = xml->getpar127(
"oscil_fm_phase",
VoicePar[nvoice].
PFMoscilphase);
VoicePar[nvoice].PFilterEnabled = xml->getparbool(
"filter_enabled",
VoicePar[nvoice].
PFilterEnabled);
VoicePar[nvoice].Pfilterbypass = xml->getparbool(
"filter_bypass",
VoicePar[nvoice].
Pfilterbypass);
VoicePar[nvoice].PFMEnabled =
xml->getpar127("fm_enabled", VoicePar[nvoice].PFMEnabled);
if(xml->enterbranch("OSCIL")) {
VoicePar[nvoice].OscilSmp->getfromXML(xml);
xml->exitbranch();
}
if(xml->enterbranch("AMPLITUDE_PARAMETERS")) {
VoicePar[nvoice].PPanning =
xml->getpar127("panning", VoicePar[nvoice].PPanning);
VoicePar[nvoice].PVolume =
xml->getpar127("volume", VoicePar[nvoice].PVolume);
VoicePar[nvoice].PVolumeminus = xml->getparbool(
"volume_minus",
VoicePar[nvoice].
PVolumeminus);
VoicePar[nvoice].PAmpVelocityScaleFunction = xml->getpar127(
"velocity_sensing",
VoicePar[nvoice].PAmpVelocityScaleFunction);
VoicePar[nvoice].PAmpEnvelopeEnabled = xml->getparbool(
"amp_envelope_enabled",
VoicePar[nvoice].PAmpEnvelopeEnabled);
if(xml->enterbranch("AMPLITUDE_ENVELOPE")) {
VoicePar[nvoice].AmpEnvelope->getfromXML(xml);
xml->exitbranch();
}
VoicePar[nvoice].PAmpLfoEnabled = xml->getparbool(
"amp_lfo_enabled",
VoicePar[nvoice].
PAmpLfoEnabled);
if(xml->enterbranch("AMPLITUDE_LFO")) {
VoicePar[nvoice].AmpLfo->getfromXML(xml);
xml->exitbranch();
}
xml->exitbranch();
}
if(xml->enterbranch("FREQUENCY_PARAMETERS")) {
VoicePar[nvoice].Pfixedfreq =
xml->getparbool("fixed_freq", VoicePar[nvoice].Pfixedfreq);
VoicePar[nvoice].PfixedfreqET = xml->getpar127(
"fixed_freq_et",
VoicePar[nvoice].
PfixedfreqET);
VoicePar[nvoice].PDetune = xml->getpar("detune",
VoicePar[nvoice].PDetune,
0,
16383);
VoicePar[nvoice].PCoarseDetune =
xml->getpar("coarse_detune",
VoicePar[nvoice].PCoarseDetune,
0,
16383);
VoicePar[nvoice].PDetuneType = xml->getpar127(
"detune_type",
VoicePar[nvoice].
PDetuneType);
VoicePar[nvoice].PFreqEnvelopeEnabled = xml->getparbool(
"freq_envelope_enabled",
VoicePar[nvoice].PFreqEnvelopeEnabled);
if(xml->enterbranch("FREQUENCY_ENVELOPE")) {
VoicePar[nvoice].FreqEnvelope->getfromXML(xml);
xml->exitbranch();
}
VoicePar[nvoice].PFreqLfoEnabled = xml->getparbool(
"freq_lfo_enabled",
VoicePar[nvoice].
PFreqLfoEnabled);
if(xml->enterbranch("FREQUENCY_LFO")) {
VoicePar[nvoice].FreqLfo->getfromXML(xml);
xml->exitbranch();
}
xml->exitbranch();
}
if(xml->enterbranch("FILTER_PARAMETERS")) {
if(xml->enterbranch("FILTER")) {
VoicePar[nvoice].VoiceFilter->getfromXML(xml);
xml->exitbranch();
}
VoicePar[nvoice].PFilterEnvelopeEnabled = xml->getparbool(
"filter_envelope_enabled",
VoicePar[nvoice].PFilterEnvelopeEnabled);
if(xml->enterbranch("FILTER_ENVELOPE")) {
VoicePar[nvoice].FilterEnvelope->getfromXML(xml);
xml->exitbranch();
}
VoicePar[nvoice].PFilterLfoEnabled = xml->getparbool(
"filter_lfo_enabled",
VoicePar[nvoice].PFilterLfoEnabled);
if(xml->enterbranch("FILTER_LFO")) {
VoicePar[nvoice].FilterLfo->getfromXML(xml);
xml->exitbranch();
}
xml->exitbranch();
}
if(xml->enterbranch("FM_PARAMETERS")) {
VoicePar[nvoice].PFMVoice =
xml->getpar("input_voice",
VoicePar[nvoice].PFMVoice,
-1,
nvoice - 1);
VoicePar[nvoice].PFMVolume =
xml->getpar127("volume", VoicePar[nvoice].PFMVolume);
VoicePar[nvoice].PFMVolumeDamp = xml->getpar127(
"volume_damp",
VoicePar[nvoice].
PFMVolumeDamp);
VoicePar[nvoice].PFMVelocityScaleFunction = xml->getpar127(
"velocity_sensing",
VoicePar[nvoice].PFMVelocityScaleFunction);
VoicePar[nvoice].PFMAmpEnvelopeEnabled = xml->getparbool(
"amp_envelope_enabled",
VoicePar[nvoice].PFMAmpEnvelopeEnabled);
if(xml->enterbranch("AMPLITUDE_ENVELOPE")) {
VoicePar[nvoice].FMAmpEnvelope->getfromXML(xml);
xml->exitbranch();
}
if(xml->enterbranch("MODULATOR")) {
VoicePar[nvoice].PFMDetune =
xml->getpar("detune", VoicePar[nvoice].PFMDetune, 0, 16383);
VoicePar[nvoice].PFMCoarseDetune = xml->getpar(
"coarse_detune",
VoicePar[nvoice].
PFMCoarseDetune,
0,
16383);
VoicePar[nvoice].PFMDetuneType = xml->getpar127(
"detune_type",
VoicePar[nvoice].
PFMDetuneType);
VoicePar[nvoice].PFMFreqEnvelopeEnabled = xml->getparbool(
"freq_envelope_enabled",
VoicePar[nvoice].PFMFreqEnvelopeEnabled);
if(xml->enterbranch("FREQUENCY_ENVELOPE")) {
VoicePar[nvoice].FMFreqEnvelope->getfromXML(xml);
xml->exitbranch();
}
if(xml->enterbranch("OSCIL")) {
VoicePar[nvoice].FMSmp->getfromXML(xml);
xml->exitbranch();
}
xml->exitbranch();
}
xml->exitbranch();
}
}

View File

@@ -1,307 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
ADnoteParameters.h - Parameters for ADnote (ADsynth)
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 AD_NOTE_PARAMETERS_H
#define AD_NOTE_PARAMETERS_H
#include "../globals.h"
#include "EnvelopeParams.h"
#include "LFOParams.h"
#include "FilterParams.h"
#include "../Synth/OscilGen.h"
#include "../Synth/Resonance.h"
#include "../Misc/Util.h"
#include "../Misc/XMLwrapper.h"
#include "../DSP/FFTwrapper.h"
#include "PresetsArray.h"
enum FMTYPE {
NONE, MORPH, RING_MOD, PHASE_MOD, FREQ_MOD, PITCH_MOD
};
extern int ADnote_unison_sizes[];
/*****************************************************************/
/* GLOBAL PARAMETERS */
/*****************************************************************/
struct ADnoteGlobalParam {
/* The instrument type - MONO/STEREO
If the mode is MONO, the panning of voices are not used
Stereo=1, Mono=0. */
unsigned char PStereo;
/******************************************
* FREQUENCY GLOBAL PARAMETERS *
******************************************/
unsigned short int PDetune; //fine detune
unsigned short int PCoarseDetune; //coarse detune+octave
unsigned char PDetuneType; //detune type
unsigned char PBandwidth; //how much the relative fine detunes of the voices are changed
EnvelopeParams *FreqEnvelope; //Frequency Envelope
LFOParams *FreqLfo; //Frequency LFO
/********************************************
* AMPLITUDE GLOBAL PARAMETERS *
********************************************/
/* Panning - 0 - random
1 - left
64 - center
127 - right */
unsigned char PPanning;
unsigned char PVolume;
unsigned char PAmpVelocityScaleFunction;
EnvelopeParams *AmpEnvelope;
LFOParams *AmpLfo;
unsigned char PPunchStrength, PPunchTime, PPunchStretch,
PPunchVelocitySensing;
/******************************************
* FILTER GLOBAL PARAMETERS *
******************************************/
FilterParams *GlobalFilter;
// filter velocity sensing
unsigned char PFilterVelocityScale;
// filter velocity sensing
unsigned char PFilterVelocityScaleFunction;
EnvelopeParams *FilterEnvelope;
LFOParams *FilterLfo;
// RESONANCE
Resonance *Reson;
//how the randomness is applied to the harmonics on more voices using the same oscillator
unsigned char Hrandgrouping;
};
/***********************************************************/
/* VOICE PARAMETERS */
/***********************************************************/
struct ADnoteVoiceParam {
/** If the voice is enabled */
unsigned char Enabled;
/** How many subvoices are used in this voice */
unsigned char Unison_size;
/** How subvoices are spread */
unsigned char Unison_frequency_spread;
/** Stereo spread of the subvoices*/
unsigned char Unison_stereo_spread;
/** Vibratto of the subvoices (which makes the unison more "natural")*/
unsigned char Unison_vibratto;
/** Medium speed of the vibratto of the subvoices*/
unsigned char Unison_vibratto_speed;
/** Unison invert phase */
unsigned char Unison_invert_phase; //0=none,1=random,2=50%,3=33%,4=25%
/** Type of the voice (0=Sound,1=Noise)*/
unsigned char Type;
/** Voice Delay */
unsigned char PDelay;
/** If the resonance is enabled for this voice */
unsigned char Presonance;
// What external oscil should I use, -1 for internal OscilSmp&FMSmp
short int Pextoscil, PextFMoscil;
// it is not allowed that the externoscil,externFMoscil => current voice
// oscillator phases
unsigned char Poscilphase, PFMoscilphase;
// filter bypass
unsigned char Pfilterbypass;
/** Voice oscillator */
OscilGen *OscilSmp;
/**********************************
* FREQUENCY PARAMETERS *
**********************************/
/** If the base frequency is fixed to 440 Hz*/
unsigned char Pfixedfreq;
/* Equal temperate (this is used only if the Pfixedfreq is enabled)
If this parameter is 0, the frequency is fixed (to 440 Hz);
if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */
unsigned char PfixedfreqET;
/** Fine detune */
unsigned short int PDetune;
/** Coarse detune + octave */
unsigned short int PCoarseDetune;
/** Detune type */
unsigned char PDetuneType;
/* Frequency Envelope */
unsigned char PFreqEnvelopeEnabled;
EnvelopeParams *FreqEnvelope;
/* Frequency LFO */
unsigned char PFreqLfoEnabled;
LFOParams *FreqLfo;
/***************************
* AMPLITUDE PARAMETERS *
***************************/
/* Panning 0 - random
1 - left
64 - center
127 - right
The Panning is ignored if the instrument is mono */
unsigned char PPanning;
/* Voice Volume */
unsigned char PVolume;
/* If the Volume negative */
unsigned char PVolumeminus;
/* Velocity sensing */
unsigned char PAmpVelocityScaleFunction;
/* Amplitude Envelope */
unsigned char PAmpEnvelopeEnabled;
EnvelopeParams *AmpEnvelope;
/* Amplitude LFO */
unsigned char PAmpLfoEnabled;
LFOParams *AmpLfo;
/*************************
* FILTER PARAMETERS *
*************************/
/* Voice Filter */
unsigned char PFilterEnabled;
FilterParams *VoiceFilter;
/* Filter Envelope */
unsigned char PFilterEnvelopeEnabled;
EnvelopeParams *FilterEnvelope;
/* LFO Envelope */
unsigned char PFilterLfoEnabled;
LFOParams *FilterLfo;
/****************************
* MODULLATOR PARAMETERS *
****************************/
/* Modullator Parameters (0=off,1=Morph,2=RM,3=PM,4=FM.. */
unsigned char PFMEnabled;
/* Voice that I use as modullator instead of FMSmp.
It is -1 if I use FMSmp(default).
It maynot be equal or bigger than current voice */
short int PFMVoice;
/* Modullator oscillator */
OscilGen *FMSmp;
/* Modullator Volume */
unsigned char PFMVolume;
/* Modullator damping at higher frequencies */
unsigned char PFMVolumeDamp;
/* Modullator Velocity Sensing */
unsigned char PFMVelocityScaleFunction;
/* Fine Detune of the Modullator*/
unsigned short int PFMDetune;
/* Coarse Detune of the Modullator */
unsigned short int PFMCoarseDetune;
/* The detune type */
unsigned char PFMDetuneType;
/* Frequency Envelope of the Modullator */
unsigned char PFMFreqEnvelopeEnabled;
EnvelopeParams *FMFreqEnvelope;
/* Frequency Envelope of the Modullator */
unsigned char PFMAmpEnvelopeEnabled;
EnvelopeParams *FMAmpEnvelope;
};
class ADnoteParameters : public PresetsArray
{
public:
ADnoteParameters(FFTwrapper *fft_);
~ADnoteParameters();
ADnoteGlobalParam GlobalPar;
ADnoteVoiceParam VoicePar[NUM_VOICES];
void defaults();
void add2XML(XMLwrapper *xml);
void getfromXML(XMLwrapper *xml);
REALTYPE getBandwidthDetuneMultiplier();
REALTYPE getUnisonFrequencySpreadCents(int nvoice);
int get_unison_size_index(int nvoice);
void set_unison_size_index(int nvoice, int index);
private:
void defaults(int n); //n is the nvoice
void EnableVoice(int nvoice);
void KillVoice(int nvoice);
FFTwrapper *fft;
void add2XMLsection(XMLwrapper *xml, int n);
void getfromXMLsection(XMLwrapper *xml, int n);
};
#endif

View File

@@ -1,19 +0,0 @@
set(zynaddsubfx_params_SRCS
ADnoteParameters.cpp
Controller.cpp
EnvelopeParams.cpp
FilterParams.cpp
LFOParams.cpp
PADnoteParameters.cpp
Presets.cpp
PresetsArray.cpp
PresetsStore.cpp
SUBnoteParameters.cpp
)
add_library(zynaddsubfx_params STATIC
${zynaddsubfx_params_SRCS}
)
target_link_libraries(zynaddsubfx_params)# ${ASOUND_LIBRARY})

View File

@@ -1,415 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Controller.cpp - (Midi) Controllers 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
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 "Controller.h"
#include <math.h>
#include <stdio.h>
Controller::Controller()
{
defaults();
resetall();
}
Controller::~Controller()
{}
void Controller::defaults()
{
setpitchwheelbendrange(100); //2 halftones
expression.receive = 1;
panning.depth = 64;
filtercutoff.depth = 64;
filterq.depth = 64;
bandwidth.depth = 64;
bandwidth.exponential = 0;
modwheel.depth = 80;
modwheel.exponential = 0;
fmamp.receive = 1;
volume.receive = 1;
sustain.receive = 1;
NRPN.receive = 1;
portamento.portamento = 0;
portamento.used = 0;
portamento.proportional = 0;
portamento.propRate = 80;
portamento.propDepth = 90;
portamento.receive = 1;
portamento.time = 64;
portamento.updowntimestretch = 64;
portamento.pitchthresh = 3;
portamento.pitchthreshtype = 1;
portamento.noteusing = -1;
resonancecenter.depth = 64;
resonancebandwidth.depth = 64;
initportamento(440.0, 440.0, false); // Now has a third argument
setportamento(0);
}
void Controller::resetall()
{
setpitchwheel(0); //center
setexpression(127);
setpanning(64);
setfiltercutoff(64);
setfilterq(64);
setbandwidth(64);
setmodwheel(64);
setfmamp(127);
setvolume(127);
setsustain(0);
setresonancecenter(64);
setresonancebw(64);
//reset the NRPN
NRPN.parhi = -1;
NRPN.parlo = -1;
NRPN.valhi = -1;
NRPN.vallo = -1;
}
void Controller::setpitchwheel(int value)
{
pitchwheel.data = value;
REALTYPE cents = value / 8192.0;
cents *= pitchwheel.bendrange;
pitchwheel.relfreq = pow(2, cents / 1200.0);
//fprintf(stderr,"%ld %ld -> %.3f\n",pitchwheel.bendrange,pitchwheel.data,pitchwheel.relfreq);fflush(stderr);
}
void Controller::setpitchwheelbendrange(unsigned short int value)
{
pitchwheel.bendrange = value;
}
void Controller::setexpression(int value)
{
expression.data = value;
if(expression.receive != 0)
expression.relvolume = value / 127.0;
else
expression.relvolume = 1.0;
}
void Controller::setpanning(int value)
{
panning.data = value;
panning.pan = (value / 128.0 - 0.5) * (panning.depth / 64.0);
}
void Controller::setfiltercutoff(int value)
{
filtercutoff.data = value;
filtercutoff.relfreq =
(value - 64.0) * filtercutoff.depth / 4096.0 * 3.321928; //3.3219..=ln2(10)
}
void Controller::setfilterq(int value)
{
filterq.data = value;
filterq.relq = pow(30.0, (value - 64.0) / 64.0 * (filterq.depth / 64.0));
}
void Controller::setbandwidth(int value)
{
bandwidth.data = value;
if(bandwidth.exponential == 0) {
REALTYPE tmp = pow(25.0, pow(bandwidth.depth / 127.0, 1.5)) - 1.0;
if((value < 64) && (bandwidth.depth >= 64))
tmp = 1.0;
bandwidth.relbw = (value / 64.0 - 1.0) * tmp + 1.0;
if(bandwidth.relbw < 0.01)
bandwidth.relbw = 0.01;
}
else
bandwidth.relbw =
pow(25.0, (value - 64.0) / 64.0 * (bandwidth.depth / 64.0));
;
}
void Controller::setmodwheel(int value)
{
modwheel.data = value;
if(modwheel.exponential == 0) {
REALTYPE tmp = pow(25.0, pow(modwheel.depth / 127.0, 1.5) * 2.0) / 25.0;
if((value < 64) && (modwheel.depth >= 64))
tmp = 1.0;
modwheel.relmod = (value / 64.0 - 1.0) * tmp + 1.0;
if(modwheel.relmod < 0.0)
modwheel.relmod = 0.0;
}
else
modwheel.relmod =
pow(25.0, (value - 64.0) / 64.0 * (modwheel.depth / 80.0));
}
void Controller::setfmamp(int value)
{
fmamp.data = value;
fmamp.relamp = value / 127.0;
if(fmamp.receive != 0)
fmamp.relamp = value / 127.0;
else
fmamp.relamp = 1.0;
}
void Controller::setvolume(int value)
{
volume.data = value;
if(volume.receive != 0)
volume.volume = pow(0.1, (127 - value) / 127.0 * 2.0);
else
volume.volume = 1.0;
}
void Controller::setsustain(int value)
{
sustain.data = value;
if(sustain.receive != 0)
sustain.sustain = ((value < 64) ? 0 : 1);
else
sustain.sustain = 0;
}
void Controller::setportamento(int value)
{
portamento.data = value;
if(portamento.receive != 0)
portamento.portamento = ((value < 64) ? 0 : 1);
}
int Controller::initportamento(REALTYPE oldfreq,
REALTYPE newfreq,
bool legatoflag)
{
portamento.x = 0.0;
if(legatoflag) { // Legato in progress
if(portamento.portamento == 0)
return 0;
}
else // No legato, do the original if...return
if((portamento.used != 0) || (portamento.portamento == 0))
return 0;
;
REALTYPE portamentotime = pow(100.0, portamento.time / 127.0) / 50.0; //portamento time in seconds
if(portamento.proportional) {
//If there is a min(float,float) and a max(float,float) then they
//could be used here
//Linear functors could also make this nicer
if(oldfreq > newfreq) //2 is the center of propRate
portamentotime *=
pow(oldfreq / newfreq / (portamento.propRate / 127.0 * 3 + .05),
(portamento.propDepth / 127.0 * 1.6 + .2));
else //1 is the center of propDepth
portamentotime *=
pow(newfreq / oldfreq / (portamento.propRate / 127.0 * 3 + .05),
(portamento.propDepth / 127.0 * 1.6 + .2));
}
if((portamento.updowntimestretch >= 64) && (newfreq < oldfreq)) {
if(portamento.updowntimestretch == 127)
return 0;
portamentotime *= pow(0.1, (portamento.updowntimestretch - 64) / 63.0);
}
if((portamento.updowntimestretch < 64) && (newfreq > oldfreq)) {
if(portamento.updowntimestretch == 0)
return 0;
portamentotime *= pow(0.1, (64.0 - portamento.updowntimestretch) / 64.0);
}
//printf("%f->%f : Time %f\n",oldfreq,newfreq,portamentotime);
portamento.dx = SOUND_BUFFER_SIZE / (portamentotime * SAMPLE_RATE);
portamento.origfreqrap = oldfreq / newfreq;
REALTYPE tmprap = ((portamento.origfreqrap > 1.0) ?
(portamento.origfreqrap) :
(1.0 / portamento.origfreqrap));
REALTYPE thresholdrap = pow(2.0, portamento.pitchthresh / 12.0);
if((portamento.pitchthreshtype == 0) && (tmprap - 0.00001 > thresholdrap))
return 0;
if((portamento.pitchthreshtype == 1) && (tmprap + 0.00001 < thresholdrap))
return 0;
portamento.used = 1;
portamento.freqrap = portamento.origfreqrap;
return 1;
}
void Controller::updateportamento()
{
if(portamento.used == 0)
return;
portamento.x += portamento.dx;
if(portamento.x > 1.0) {
portamento.x = 1.0;
portamento.used = 0;
}
portamento.freqrap =
(1.0 - portamento.x) * portamento.origfreqrap + portamento.x;
}
void Controller::setresonancecenter(int value)
{
resonancecenter.data = value;
resonancecenter.relcenter =
pow(3.0, (value - 64.0) / 64.0 * (resonancecenter.depth / 64.0));
}
void Controller::setresonancebw(int value)
{
resonancebandwidth.data = value;
resonancebandwidth.relbw =
pow(1.5, (value - 64.0) / 64.0 * (resonancebandwidth.depth / 127.0));
}
//Returns 0 if there is NRPN or 1 if there is not
int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo)
{
if(NRPN.receive == 0)
return 1;
if((NRPN.parhi < 0) || (NRPN.parlo < 0) || (NRPN.valhi < 0)
|| (NRPN.vallo < 0))
return 1;
*parhi = NRPN.parhi;
*parlo = NRPN.parlo;
*valhi = NRPN.valhi;
*vallo = NRPN.vallo;
return 0;
}
void Controller::setparameternumber(unsigned int type, int value)
{
switch(type) {
case C_nrpnhi:
NRPN.parhi = value;
NRPN.valhi = -1;
NRPN.vallo = -1; //clear the values
break;
case C_nrpnlo:
NRPN.parlo = value;
NRPN.valhi = -1;
NRPN.vallo = -1; //clear the values
break;
case C_dataentryhi:
if((NRPN.parhi >= 0) && (NRPN.parlo >= 0))
NRPN.valhi = value;
break;
case C_dataentrylo:
if((NRPN.parhi >= 0) && (NRPN.parlo >= 0))
NRPN.vallo = value;
break;
}
}
void Controller::add2XML(XMLwrapper *xml)
{
xml->addpar("pitchwheel_bendrange", pitchwheel.bendrange);
xml->addparbool("expression_receive", expression.receive);
xml->addpar("panning_depth", panning.depth);
xml->addpar("filter_cutoff_depth", filtercutoff.depth);
xml->addpar("filter_q_depth", filterq.depth);
xml->addpar("bandwidth_depth", bandwidth.depth);
xml->addpar("mod_wheel_depth", modwheel.depth);
xml->addparbool("mod_wheel_exponential", modwheel.exponential);
xml->addparbool("fm_amp_receive", fmamp.receive);
xml->addparbool("volume_receive", volume.receive);
xml->addparbool("sustain_receive", sustain.receive);
xml->addparbool("portamento_receive", portamento.receive);
xml->addpar("portamento_time", portamento.time);
xml->addpar("portamento_pitchthresh", portamento.pitchthresh);
xml->addpar("portamento_pitchthreshtype", portamento.pitchthreshtype);
xml->addpar("portamento_portamento", portamento.portamento);
xml->addpar("portamento_updowntimestretch", portamento.updowntimestretch);
xml->addpar("portamento_proportional", portamento.proportional);
xml->addpar("portamento_proprate", portamento.propRate);
xml->addpar("portamento_propdepth", portamento.propDepth);
xml->addpar("resonance_center_depth", resonancecenter.depth);
xml->addpar("resonance_bandwidth_depth", resonancebandwidth.depth);
}
void Controller::getfromXML(XMLwrapper *xml)
{
pitchwheel.bendrange = xml->getpar("pitchwheel_bendrange",
pitchwheel.bendrange,
-6400,
6400);
expression.receive = xml->getparbool("expression_receive",
expression.receive);
panning.depth = xml->getpar127("panning_depth", panning.depth);
filtercutoff.depth = xml->getpar127("filter_cutoff_depth",
filtercutoff.depth);
filterq.depth = xml->getpar127("filter_q_depth", filterq.depth);
bandwidth.depth = xml->getpar127("bandwidth_depth", bandwidth.depth);
modwheel.depth = xml->getpar127("mod_wheel_depth", modwheel.depth);
modwheel.exponential = xml->getparbool("mod_wheel_exponential",
modwheel.exponential);
fmamp.receive = xml->getparbool("fm_amp_receive",
fmamp.receive);
volume.receive = xml->getparbool("volume_receive",
volume.receive);
sustain.receive = xml->getparbool("sustain_receive",
sustain.receive);
portamento.receive = xml->getparbool("portamento_receive",
portamento.receive);
portamento.time = xml->getpar127("portamento_time",
portamento.time);
portamento.pitchthresh = xml->getpar127("portamento_pitchthresh",
portamento.pitchthresh);
portamento.pitchthreshtype = xml->getpar127("portamento_pitchthreshtype",
portamento.pitchthreshtype);
portamento.portamento = xml->getpar127("portamento_portamento",
portamento.portamento);
portamento.updowntimestretch = xml->getpar127(
"portamento_updowntimestretch",
portamento.updowntimestretch);
portamento.proportional = xml->getpar127("portamento_proportional",
portamento.proportional);
portamento.propRate = xml->getpar127("portamento_proprate",
portamento.propRate);
portamento.propDepth = xml->getpar127("portamento_propdepth",
portamento.propDepth);
resonancecenter.depth = xml->getpar127("resonance_center_depth",
resonancecenter.depth);
resonancebandwidth.depth = xml->getpar127("resonance_bandwidth_depth",
resonancebandwidth.depth);
}

View File

@@ -1,221 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
Controller.h - (Midi) Controllers 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
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 CONTROLLER_H
#define CONTROLLER_H
#include "../globals.h"
#include "../Misc/XMLwrapper.h"
/**(Midi) Controllers implementation*/
class Controller
{
public:
Controller();
~Controller();
void resetall();
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
//Controllers functions
void setpitchwheel(int value);
void setpitchwheelbendrange(unsigned short int value);
void setexpression(int value);
void setpanning(int value);
void setfiltercutoff(int value);
void setfilterq(int value);
void setbandwidth(int value);
void setmodwheel(int value);
void setfmamp(int value);
void setvolume(int value);
void setsustain(int value);
/**Enable or disable portamento
* @param value 0-127 MIDI value (greater than 64 enables)*/
void setportamento(int value);
void setresonancecenter(int value);
void setresonancebw(int value);
void setparameternumber(unsigned int type, int value); //used for RPN and NRPN's
int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo);
/**
* Initialize a portamento
*
* @param oldfreq Starting frequency of the portamento (Hz)
* @param newfreq Ending frequency of the portamento (Hz)
* @param legatoflag true when legato is in progress, false otherwise
* @returns 1 if properly initialized, 0 otherwise*/
int initportamento(REALTYPE oldfreq, REALTYPE newfreq, bool legatoflag);
/**Update portamento's freqrap to next value based upon dx*/
void updateportamento();
// Controllers values
struct { //Pitch Wheel
int data;
short int bendrange; //bendrange is in cents
REALTYPE relfreq; //the relative frequency (default is 1.0)
} pitchwheel;
struct { //Expression
int data;
REALTYPE relvolume;
unsigned char receive;
} expression;
struct { //Panning
int data;
REALTYPE pan;
unsigned char depth;
} panning;
struct { //Filter cutoff
int data;
REALTYPE relfreq;
unsigned char depth;
} filtercutoff;
struct { //Filter Q
int data;
REALTYPE relq;
unsigned char depth;
} filterq;
struct { //Bandwidth
int data;
REALTYPE relbw;
unsigned char depth;
unsigned char exponential;
} bandwidth;
struct { //Modulation Wheel
int data;
REALTYPE relmod;
unsigned char depth;
unsigned char exponential;
} modwheel;
struct { //FM amplitude
int data;
REALTYPE relamp;
unsigned char receive;
} fmamp;
struct { //Volume
int data;
REALTYPE volume;
unsigned char receive;
} volume;
struct { //Sustain
int data, sustain;
unsigned char receive;
} sustain;
struct { /**<Portamento*/
//parameters
int data;
unsigned char portamento;
/**Whether the portamento midi events are received or not*/
unsigned char receive;
/** The time that it takes for the portamento to complete
*
* Translates in an expontal fashion to 0 Seconds to 1.93 Seconds
* of completion time*/
unsigned char time;
/**If the portamento is proportinal to the distance spanned
*
* 0 - constant time(default)
* 1 - proportional*/
unsigned char proportional;
/**Rate of proportinal portamento*/
unsigned char propRate;
/**Depth of proportinal portamento*/
unsigned char propDepth;
/**pitchthresh is the threshold of enabling protamento*/
unsigned char pitchthresh;
/**enable the portamento only below(0)/above(1) the threshold*/
unsigned char pitchthreshtype;
/**this value represent how the portamento time is reduced
* 0 - for down portamento
* 1-63 - the up portamento's time is smaller than the down portamento
* 64 - the portamento time is always the same
* 64-126 - the down portamento's time is smaller than the up portamento
* 127 - for upper portamento
* 'up portamento' means when the frequency is rising
* (eg: the portamento is from 200Hz to 300 Hz)
* 'down portamento' means when the frequency is lowering
* (eg: the portamento is from 300Hz to 200 Hz)
*/
unsigned char updowntimestretch;
/**this value is used to compute the actual portamento
*
* This is a multiplyer to change the frequency of the newer
* frequency to fit the profile of the portamento.
* This will be linear with respect to x.*/
REALTYPE freqrap;
/**this is used by the Part for knowing which note uses the portamento*/
int noteusing;
/**if a the portamento is used by a note
* \todo see if this can be a bool*/
int used;
//Internal data
/**x is from 0.0 (start portamento) to 1.0 (finished portamento)*/
REALTYPE x;
/**dx is the increment to x when updateportamento is called*/
REALTYPE dx;
/** this is used for computing oldfreq value from x*/
REALTYPE origfreqrap;
} portamento;
struct { //Resonance Center Frequency
int data;
REALTYPE relcenter;
unsigned char depth;
} resonancecenter;
struct { //Resonance Bandwidth
int data;
REALTYPE relbw;
unsigned char depth;
} resonancebandwidth;
/** RPN and NPRPN */
struct { //nrpn
int parhi, parlo;
int valhi, vallo;
unsigned char receive; //this is saved to disk by Master
} NRPN;
private:
};
#endif

View File

@@ -1,298 +0,0 @@
/*
ZynAddSubFX - a software synthesizer
EnvelopeParams.cpp - Parameters for Envelope
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 <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "EnvelopeParams.h"
EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,
unsigned char Pforcedrelease_):Presets()
{
int i;
PA_dt = 10;
PD_dt = 10;
PR_dt = 10;
PA_val = 64;
PD_val = 64;
PS_val = 64;
PR_val = 64;
for(i = 0; i < MAX_ENVELOPE_POINTS; i++) {
Penvdt[i] = 32;
Penvval[i] = 64;
}
Penvdt[0] = 0; //no used
Penvsustain = 1;
Penvpoints = 1;
Envmode = 1;
Penvstretch = Penvstretch_;
Pforcedrelease = Pforcedrelease_;
Pfreemode = 1;
Plinearenvelope = 0;
store2defaults();
}
EnvelopeParams::~EnvelopeParams()
{}
REALTYPE EnvelopeParams::getdt(char i)
{
REALTYPE result = (pow(2.0, Penvdt[(int)i] / 127.0 * 12.0) - 1.0) * 10.0; //miliseconds
return result;
}
/*
* ADSR/ASR... initialisations
*/
void EnvelopeParams::ADSRinit(char A_dt, char D_dt, char S_val, char R_dt)
{
setpresettype("Penvamplitude");
Envmode = 1;
PA_dt = A_dt;
PD_dt = D_dt;
PS_val = S_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
}
void EnvelopeParams::ADSRinit_dB(char A_dt, char D_dt, char S_val, char R_dt)
{
setpresettype("Penvamplitude");
Envmode = 2;
PA_dt = A_dt;
PD_dt = D_dt;
PS_val = S_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
}
void EnvelopeParams::ASRinit(char A_val, char A_dt, char R_val, char R_dt)
{
setpresettype("Penvfrequency");
Envmode = 3;
PA_val = A_val;
PA_dt = A_dt;
PR_val = R_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
}
void EnvelopeParams::ADSRinit_filter(char A_val,
char A_dt,
char D_val,
char D_dt,
char R_dt,
char R_val)
{
setpresettype("Penvfilter");
Envmode = 4;
PA_val = A_val;
PA_dt = A_dt;
PD_val = D_val;
PD_dt = D_dt;
PR_dt = R_dt;
PR_val = R_val;
Pfreemode = 0;
converttofree();
store2defaults();
}
void EnvelopeParams::ASRinit_bw(char A_val, char A_dt, char R_val, char R_dt)
{
setpresettype("Penvbandwidth");
Envmode = 5;
PA_val = A_val;
PA_dt = A_dt;
PR_val = R_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
}
/*
* Convert the Envelope to freemode
*/
void EnvelopeParams::converttofree()
{
switch(Envmode) {
case 1:
Penvpoints = 4;
Penvsustain = 2;
Penvval[0] = 0;
Penvdt[1] = PA_dt;
Penvval[1] = 127;
Penvdt[2] = PD_dt;
Penvval[2] = PS_val;
Penvdt[3] = PR_dt;
Penvval[3] = 0;
break;
case 2:
Penvpoints = 4;
Penvsustain = 2;
Penvval[0] = 0;
Penvdt[1] = PA_dt;
Penvval[1] = 127;
Penvdt[2] = PD_dt;
Penvval[2] = PS_val;
Penvdt[3] = PR_dt;
Penvval[3] = 0;
break;
case 3:
Penvpoints = 3;
Penvsustain = 1;
Penvval[0] = PA_val;
Penvdt[1] = PA_dt;
Penvval[1] = 64;
Penvdt[2] = PR_dt;
Penvval[2] = PR_val;
break;
case 4:
Penvpoints = 4;
Penvsustain = 2;
Penvval[0] = PA_val;
Penvdt[1] = PA_dt;
Penvval[1] = PD_val;
Penvdt[2] = PD_dt;
Penvval[2] = 64;
Penvdt[3] = PR_dt;
Penvval[3] = PR_val;
break;
case 5:
Penvpoints = 3;
Penvsustain = 1;
Penvval[0] = PA_val;
Penvdt[1] = PA_dt;
Penvval[1] = 64;
Penvdt[2] = PR_dt;
Penvval[2] = PR_val;
break;
}
}
void EnvelopeParams::add2XML(XMLwrapper *xml)
{
xml->addparbool("free_mode", Pfreemode);
xml->addpar("env_points", Penvpoints);
xml->addpar("env_sustain", Penvsustain);
xml->addpar("env_stretch", Penvstretch);
xml->addparbool("forced_release", Pforcedrelease);
xml->addparbool("linear_envelope", Plinearenvelope);
xml->addpar("A_dt", PA_dt);
xml->addpar("D_dt", PD_dt);
xml->addpar("R_dt", PR_dt);
xml->addpar("A_val", PA_val);
xml->addpar("D_val", PD_val);
xml->addpar("S_val", PS_val);
xml->addpar("R_val", PR_val);
if((Pfreemode != 0) || (!xml->minimal)) {
for(int i = 0; i < Penvpoints; i++) {
xml->beginbranch("POINT", i);
if(i != 0)
xml->addpar("dt", Penvdt[i]);
xml->addpar("val", Penvval[i]);
xml->endbranch();
}
}
}
void EnvelopeParams::getfromXML(XMLwrapper *xml)
{
Pfreemode = xml->getparbool("free_mode", Pfreemode);
Penvpoints = xml->getpar127("env_points", Penvpoints);
Penvsustain = xml->getpar127("env_sustain", Penvsustain);
Penvstretch = xml->getpar127("env_stretch", Penvstretch);
Pforcedrelease = xml->getparbool("forced_release", Pforcedrelease);
Plinearenvelope = xml->getparbool("linear_envelope", Plinearenvelope);
PA_dt = xml->getpar127("A_dt", PA_dt);
PD_dt = xml->getpar127("D_dt", PD_dt);
PR_dt = xml->getpar127("R_dt", PR_dt);
PA_val = xml->getpar127("A_val", PA_val);
PD_val = xml->getpar127("D_val", PD_val);
PS_val = xml->getpar127("S_val", PS_val);
PR_val = xml->getpar127("R_val", PR_val);
for(int i = 0; i < Penvpoints; i++) {
if(xml->enterbranch("POINT", i) == 0)
continue;
if(i != 0)
Penvdt[i] = xml->getpar127("dt", Penvdt[i]);
Penvval[i] = xml->getpar127("val", Penvval[i]);
xml->exitbranch();
}
if(!Pfreemode)
converttofree();
}
void EnvelopeParams::defaults()
{
Penvstretch = Denvstretch;
Pforcedrelease = Dforcedrelease;
Plinearenvelope = Dlinearenvelope;
PA_dt = DA_dt;
PD_dt = DD_dt;
PR_dt = DR_dt;
PA_val = DA_val;
PD_val = DD_val;
PS_val = DS_val;
PR_val = DR_val;
Pfreemode = 0;
converttofree();
}
void EnvelopeParams::store2defaults()
{
Denvstretch = Penvstretch;
Dforcedrelease = Pforcedrelease;
Dlinearenvelope = Plinearenvelope;
DA_dt = PA_dt;
DD_dt = PD_dt;
DR_dt = PR_dt;
DA_val = PA_val;
DD_val = PD_val;
DS_val = PS_val;
DR_val = PR_val;
}

Some files were not shown because too many files have changed in this diff Show More