1 /* B.Oops
2  * Glitch effect sequencer LV2 plugin
3  *
4  * Copyright (C) 2020 by Sven Jähnichen
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 #ifndef FXWAVESHAPER_HPP_
22 #define FXWAVESHAPER_HPP_
23 
24 #include "Fx.hpp"
25 #include "Shape.hpp"
26 
27 #ifndef DB2CO
28 #define DB2CO(x) (pow (10, 0.05 * (x)))
29 #endif
30 
31 #ifndef CO2DB
32 #define CO2DB(x) (20.0 * log10 (x))
33 #endif
34 
35 #ifndef SGN
36 #define SGN(x) (((x) > 0) - ((x) < 0))
37 #endif
38 
39 #define FX_WAVESHAPER_DRIVE 0
40 #define FX_WAVESHAPER_DRIVERAND 1
41 #define FX_WAVESHAPER_GAIN 2
42 #define FX_WAVESHAPER_GAINRAND 3
43 #define FX_WAVESHAPER_UNIT 4
44 
45 class FxWaveshaper : public Fx
46 {
47 public:
48 	FxWaveshaper () = delete;
49 
FxWaveshaper(RingBuffer<Stereo> ** buffer,float * params,Pad * pads,Shape<SHAPE_MAXNODES> * shape)50 	FxWaveshaper (RingBuffer<Stereo>** buffer, float* params, Pad* pads, Shape<SHAPE_MAXNODES>* shape) :
51 		Fx (buffer, params, pads),
52 		shape (shape),
53 		drive (500.0f),
54 		gain (0.5f),
55 		unit (0)
56 	{
57 		if (!shape) throw std::invalid_argument ("Fx initialized with shape nullptr");
58 	}
59 
init(const double position)60 	virtual void init (const double position) override
61 	{
62 		Fx::init (position);
63 		const double r1 = bidist (rnd);
64 		drive = DB2CO (-30.0 + 100.0 * LIMIT (params[SLOTS_OPTPARAMS + FX_WAVESHAPER_DRIVE] + r1 * params[SLOTS_OPTPARAMS + FX_WAVESHAPER_DRIVERAND], 0.00, 1.0));
65 		const double r2 = bidist (rnd);
66 		gain = DB2CO (-70.0 + 100.0 * LIMIT (params[SLOTS_OPTPARAMS + FX_WAVESHAPER_GAIN] + r2 * params[SLOTS_OPTPARAMS + FX_WAVESHAPER_GAINRAND], 0.0, 1.0));
67 		unit = LIMIT (params[SLOTS_OPTPARAMS + FX_WAVESHAPER_UNIT], 0, 1);
68 	}
69 
process(const double position,const double size)70 	virtual Stereo process (const double position, const double size) override
71 	{
72 		const Stereo s0 = (**buffer).front();
73 		float l;
74 		float r;
75 		float lf;
76 		float rf;
77 
78 		if (unit == 0)
79 		{
80 			l = fabsf (s0.left * drive);
81 			r = fabsf (s0.right * drive);
82 			l = LIMIT (l, 0.0f, 1.0f);
83 			r = LIMIT (r, 0.0f, 1.0f);
84 			lf = shape->getMapValue (l);
85 			rf = shape->getMapValue (r);
86 		}
87 
88 		else
89 		{
90 			l = (90.0f + CO2DB (fabsf (0.000031623f + s0.left * drive))) / 120.0f;
91 			r = (90.0f + CO2DB (fabsf (0.000031623f + s0.right * drive))) / 120.0f;
92 			l = LIMIT (l, 0.0f, 1.0f);
93 			r = LIMIT (r, 0.0f, 1.0f);
94 			lf = DB2CO (-90.0f + shape->getMapValue (l) * 120.0f);
95 			rf = DB2CO (-90.0f + shape->getMapValue (r) * 120.0f);
96 		}
97 
98 		return Stereo (SGN (s0.left) * lf * gain, SGN (s0.right) * rf * gain);
99 	}
100 
101 protected:
102 	Shape<SHAPE_MAXNODES>* shape;
103 	float drive;
104 	float gain;
105 	int unit;
106 };
107 
108 #endif /* FXWAVESHAPER_HPP_ */
109