zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 7d5373494d1d84d6cdfe32d50d781f462a889bc7
parent 1f63d5cee8b9394149ad9ec88000069040adbc54
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Thu, 18 Aug 2011 22:04:47 -0400

Distortion: Moving nonlinear waveshaping code

Diffstat:
Msrc/Effects/Distorsion.cpp | 181+++----------------------------------------------------------------------------
Msrc/Effects/Distorsion.h | 5-----
Msrc/Misc/CMakeLists.txt | 7++++---
Asrc/Misc/WaveShapeSmps.cpp | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Misc/WaveShapeSmps.h | 31+++++++++++++++++++++++++++++++
Msrc/Synth/OscilGen.cpp | 7++++---
6 files changed, 233 insertions(+), 187 deletions(-)

diff --git a/src/Effects/Distorsion.cpp b/src/Effects/Distorsion.cpp @@ -20,181 +20,10 @@ */ -#include <cmath> -#include "../DSP/AnalogFilter.h" #include "Distorsion.h" - - -/* - * Waveshape (this is called by OscilGen::waveshape and Distorsion::process) - */ - -void waveshapesmps(int n, - float *smps, - unsigned char type, - unsigned char drive) -{ - int i; - float ws = drive / 127.0; - float 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++) { - float 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++) { - float 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++) { - float 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++) { - float 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++) { - float 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++) { - float 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++) { - float 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*/ - } -} - +#include "../DSP/AnalogFilter.h" +#include "../Misc/WaveShapeSmps.h" +#include <cmath> Distorsion::Distorsion(const int &insertion_, float *efxoutl_, @@ -287,9 +116,9 @@ void Distorsion::out(const Stereo<float *> &smp) applyfilters(efxoutl, efxoutr); //no optimised, yet (no look table) - waveshapesmps(SOUND_BUFFER_SIZE, efxoutl, Ptype + 1, Pdrive); + waveShapeSmps(SOUND_BUFFER_SIZE, efxoutl, Ptype + 1, Pdrive); if(Pstereo != 0) - waveshapesmps(SOUND_BUFFER_SIZE, efxoutr, Ptype + 1, Pdrive); + waveShapeSmps(SOUND_BUFFER_SIZE, efxoutr, Ptype + 1, Pdrive); if(Pprefiltering == 0) applyfilters(efxoutl, efxoutr); diff --git a/src/Effects/Distorsion.h b/src/Effects/Distorsion.h @@ -26,11 +26,6 @@ #include "../globals.h" #include "Effect.h" -//Waveshaping(called by Distorsion effect and waveshape from OscilGen) -void waveshapesmps(int n, - float *smps, - unsigned char type, - unsigned char drive); /**Distortion Effect*/ class Distorsion:public Effect { diff --git a/src/Misc/CMakeLists.txt b/src/Misc/CMakeLists.txt @@ -9,8 +9,9 @@ set(zynaddsubfx_misc_SRCS Part.cpp Util.cpp XMLwrapper.cpp - Recorder.cpp - WavFile.cpp + Recorder.cpp + WavFile.cpp + WaveShapeSmps.cpp ) if(LashEnable) @@ -18,7 +19,7 @@ if(LashEnable) endif() add_library(zynaddsubfx_misc STATIC - ${zynaddsubfx_misc_SRCS} + ${zynaddsubfx_misc_SRCS} ) target_link_libraries(zynaddsubfx_misc zynaddsubfx_nio) diff --git a/src/Misc/WaveShapeSmps.cpp b/src/Misc/WaveShapeSmps.cpp @@ -0,0 +1,189 @@ +/* + ZynAddSubFX - a software synthesizer + + WaveShapeSmps.cpp - Sample Distortion + 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 "WaveShapeSmps.h" +#include <cmath> + +void waveShapeSmps(int n, + float *smps, + unsigned char type, + unsigned char drive) +{ + int i; + float ws = drive / 127.0; + float 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++) { + float 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++) { + float 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++) { + float 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++) { + float 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++) { + float 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++) { + float 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++) { + float 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; + } +} diff --git a/src/Misc/WaveShapeSmps.h b/src/Misc/WaveShapeSmps.h @@ -0,0 +1,31 @@ +/* + ZynAddSubFX - a software synthesizer + + WaveShapeSmps.h - Sample distortions + 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 WAVESHAPESMPS_H +#define WAVESHAPESMPS_H + +//Waveshaping(called by Distorsion effect and waveshape from OscilGen) +void waveShapeSmps(int n, + float *smps, + unsigned char type, + unsigned char drive); + +#endif diff --git a/src/Synth/OscilGen.cpp b/src/Synth/OscilGen.cpp @@ -20,13 +20,14 @@ */ +#include "OscilGen.h" +#include "../Misc/WaveShapeSmps.h" + #include <cassert> #include <stdlib.h> #include <math.h> #include <stdio.h> -#include "OscilGen.h" -#include "../Effects/Distorsion.h" OscilGen::OscilGen(FFTwrapper *fft_, Resonance *res_):Presets() @@ -342,7 +343,7 @@ void OscilGen::waveshape() tmpsmps[i] *= max; //Do the waveshaping - waveshapesmps(OSCIL_SIZE, tmpsmps, Pwaveshapingfunction, Pwaveshaping); + waveShapeSmps(OSCIL_SIZE, tmpsmps, Pwaveshapingfunction, Pwaveshaping); fft->smps2freqs(tmpsmps, oscilFFTfreqs); //perform FFT }