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 FXFLANGER_HPP_
22 #define FXFLANGER_HPP_
23 
24 #include "Fx.hpp"
25 
26 #define FX_FLANGER_MINDELAY 0
27 #define FX_FLANGER_MINDELAYRAND 1
28 #define FX_FLANGER_MODDELAY 2
29 #define FX_FLANGER_MODDELAYRAND 3
30 #define FX_FLANGER_FREQ 4
31 #define FX_FLANGER_FREQRAND 5
32 #define FX_FLANGER_PHASE 6
33 #define FX_FLANGER_PHASERAND 7
34 #define FX_FLANGER_FEEDBACK 8
35 #define FX_FLANGER_FEEDBACKRAND 9
36 
37 class FxFlanger : public Fx
38 {
39 public:
40 	FxFlanger () = delete;
41 
FxFlanger(RingBuffer<Stereo> ** buffer,float * params,Pad * pads,double * framesPerStep,double rate)42 	FxFlanger (RingBuffer<Stereo>** buffer, float* params, Pad* pads, double* framesPerStep, double rate) :
43 		Fx (buffer, params, pads),
44 		samplerate (rate),
45 		framesPerStepPtr (framesPerStep),
46 		framesPerStep (24000),
47 		minDelay (0.0),
48 		modDelay (0.01),
49 		freq (0.25),
50 		phase (0.0),
51 		feedback (0.0f)
52 	{
53 		if (!framesPerStep) throw std::invalid_argument ("Fx initialized with framesPerStep nullptr");
54 	}
55 
init(const double position)56 	virtual void init (const double position) override
57 	{
58 		Fx::init (position);
59 		const double r1 = bidist (rnd);
60 		minDelay = 0.01 * LIMIT (params[SLOTS_OPTPARAMS + FX_FLANGER_MINDELAY] + r1 * params[SLOTS_OPTPARAMS + FX_FLANGER_MINDELAYRAND], 0.0, 1.0);
61 		const double r2 = bidist (rnd);
62 		modDelay = 0.01 * LIMIT (params[SLOTS_OPTPARAMS + FX_FLANGER_MODDELAY] + r2 * params[SLOTS_OPTPARAMS + FX_FLANGER_MODDELAYRAND], 0.0, 1.0);
63 		const double r3 = bidist (rnd);
64 		freq = 10.0 * 2.0 * M_PI * pow (LIMIT (params[SLOTS_OPTPARAMS + FX_FLANGER_FREQ] + r3 * params[SLOTS_OPTPARAMS + FX_FLANGER_FREQRAND], 0.0, 1.0), 3.0);
65 		const double r4 = bidist (rnd);
66 		phase = 2.0 * M_PI * LIMIT (params[SLOTS_OPTPARAMS + FX_FLANGER_PHASE] + r4 * params[SLOTS_OPTPARAMS + FX_FLANGER_PHASERAND], 0.0, 1.0);
67 		const double r5 = bidist (rnd);
68 		feedback = 2.0 * LIMIT (params[SLOTS_OPTPARAMS + FX_FLANGER_FEEDBACK] + r5 * params[SLOTS_OPTPARAMS + FX_FLANGER_FEEDBACKRAND], 0.0, 1.0) - 1.0;
69 		framesPerStep = *framesPerStepPtr;
70 	}
71 
process(const double position,const double size)72 	virtual Stereo process (const double position, const double size) override
73 	{
74 		const double delayL = minDelay + (0.5 - 0.5 * cos (freq * position * framesPerStep / samplerate)) * modDelay;
75 		const double delayR = minDelay + (0.5 - 0.5 * cos (phase + freq * position * framesPerStep / samplerate)) * modDelay;
76 		const long frameL = (delayL * samplerate);
77 		const long frameR = (delayR * samplerate);
78 		return Stereo ((**buffer)[frameL].left, (**buffer)[frameR].right);
79 	}
80 
playPad(const double position,const double size,const double mixf)81 	virtual Stereo playPad (const double position, const double size, const double mixf) override
82 	{
83 		const Stereo s0 = (**buffer).front();
84 		Stereo s1 = process (position, size);
85 		s1 = mix (s0, s1, position, size, mixf);
86 		Stereo s2 = s1;
87 		(**buffer).front() = s2.mix (s0, 1.0f - feedback);
88 		return s1;
89 	}
90 
play(const double position,const double size,const double mx,const double mixf)91 	virtual Stereo play (const double position, const double size, const double mx, const double mixf) override
92 	{
93 		const Stereo s0 = (**buffer).front();
94 		Stereo s1 = process (position, size);
95 		s1 = BUtilities::mix<Stereo> (s0, pan (s0, s1), params[SLOTS_MIX] * mx * mixf);
96 		Stereo s2 = s1;
97 		(**buffer).front() = s2.mix (s0, 1.0f - feedback);
98 		return s1;
99 	}
100 
101 protected:
102 	double samplerate;
103 	double* framesPerStepPtr;
104 	double framesPerStep;
105 	double minDelay;
106 	double modDelay;
107 	double freq;
108 	double phase;
109 	float feedback;
110 };
111 
112 #endif /* FXFLANGER_HPP_ */
113