1 /*
2 	Scape.cc
3 
4 	Copyright 2004-13 Tim Goetze <tim@quitte.de>
5 
6 	http://quitte.de/dsp/
7 
8 */
9 /*
10 	This program is free software; you can redistribute it and/or
11 	modify it under the terms of the GNU General Public License
12 	as published by the Free Software Foundation; either version 3
13 	of the License, or (at your option) any later version.
14 
15 	This program is distributed in the hope that it will be useful,
16 	but WITHOUT ANY WARRANTY; without even the implied warranty of
17 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 	GNU General Public License for more details.
19 
20 	You should have received a copy of the GNU General Public License
21 	along with this program; if not, write to the Free Software
22 	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 	02111-1307, USA or point your web browser to http://www.gnu.org.
24 */
25 
26 #include "basics.h"
27 
28 #include "Scape.h"
29 #include "Descriptor.h"
30 
31 static double
32 dividers [] = {
33 	1 /* not used, 0 sentinel */,
34 	1, 0.5, 0.66666666666666666667,	0.75
35 };
36 
37 static float
frandom2()38 frandom2()
39 {
40 	float f = frandom();
41 	return f*f*f;
42 }
43 
44 void
init()45 Scape::init()
46 {
47 	delay.init ((int) (2.01 * fs)); /* two seconds = 30 bpm + */
48 	for (int i = 0; i < 2; ++i)
49 	{
50 		lfo[i].lorenz.init(),
51 		lfo[i].lorenz.set_rate (.00000001*fs);
52 		lfo[i].lp.set_f (3*over_fs);
53 	}
54 }
55 
56 void
activate()57 Scape::activate()
58 {
59 	time = 0;
60 	fb = 0;
61 
62 	for (int i = 0; i < 4; ++i)
63 		svf[i].reset(),
64 		svf[i].set_out (1), /* band pass */
65 		hipass[i].set_f (250*over_fs);
66 
67 	delay.reset();
68 	period = 0;
69 }
70 
71 inline double
pick_f(float range,float tune)72 pick_f (float range, float tune)
73 {
74 	static float over_12 = 1./12;
75 	int n = 48 + (int) (4*12*range*frandom());
76 	return tune*pow(2,(n-69)*over_12);
77 }
78 
79 
80 void
cycle(uint frames)81 Scape::cycle (uint frames)
82 {
83 	/* delay times */
84 	double t1 = 60*fs/getport(0);
85 	int div = (int) getport(1);
86 	double t2 = t1*dividers[div];
87 
88 
89 	float q = .99*getport(2);
90 	float blend = pow(getport(3),.2);
91 	float dry = sqrt(1-blend*blend);
92 	fb = .94*getport(4);
93 
94 	float tune = 440;
95 
96 	sample_t * s = ports[5];
97 	sample_t * dl = ports[6];
98 	sample_t * dr = ports[7];
99 
100 	DSP::FPTruncateMode truncate;
101 
102 	while (frames)
103 	{
104 		/* retune filters */
105 		if (period <= 1)
106 		{
107 			period = .5*t2;
108 			float f;
109 
110 			f = frandom2();
111 			svf[0].set_f_Q (pick_f(.3,tune)*over_fs, q);
112 			svf[3].set_f_Q (pick_f(.5,tune)*over_fs, q); /* LP */
113 
114 			f = frandom2();
115 			svf[1].set_f_Q (pick_f(.8,tune)*over_fs, f*q);
116 			svf[2].set_f_Q (pick_f(.9,tune)*over_fs, .5*f*q);
117 		}
118 
119 		uint n = min((uint) period, frames);
120 		for (uint i=0; i < n; ++i)
121 		{
122 			sample_t x = s[i] + normal;
123 
124 			sample_t x1 = delay.get_linear (t1);
125 			sample_t x2 = delay.get_linear (t2);
126 
127 			delay.put (x + fb*x1);
128 			x = dry*x + .1*svf[0].process (x) + .2*svf[3].process(x);
129 
130 			x1 = svf[1].process(x1 - normal);
131 			x2 = svf[2].process(x2 - normal);
132 
133 			x1 = hipass[1].process(x1);
134 			x2 = hipass[2].process(x2);
135 
136 			sample_t x1l, x1r, x2l, x2r;
137 			x1l = .7*fabs(lfo[0].get());
138 			x1r = 1 - x1l;
139 			x2r = .7*fabs(lfo[1].get());
140 			x2l = 1 - x2r;
141 
142 			dl[i] = x + blend*(x1*x1l + x2*x2l);
143 			dr[i] = x + blend*(x1*x1r + x2*x2r);
144 		}
145 
146 		frames -= n;
147 		period -= n;
148 		s += n;
149 		dl += n;
150 		dr += n;
151 	}
152 }
153 
154 /* //////////////////////////////////////////////////////////////////////// */
155 
156 PortInfo
157 Scape::port_info [] =
158 {
159 	{ "bpm", CTRL_IN, {DEFAULT_MID, 30, 182} },
160 	{	"div", CTRL_IN, {INTEGER | DEFAULT_MIN, 2, 4},
161 		"{2:'♪♪',3:'♪♪♪',4:'♬♬'}" },
162 
163 	{ "Q", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} },
164 	{ "blend", CTRL_IN, {DEFAULT_MID, 0, 1} },
165 	{ "feedback", CTRL_IN, {DEFAULT_LOW, 0, 1} },
166 
167 	{ "in", AUDIO_IN },
168 	{ "out.l", AUDIO_OUT },
169 	{ "out.r", AUDIO_OUT }
170 };
171 
172 template <> void
setup()173 Descriptor<Scape>::setup()
174 {
175 	Label = "Scape";
176 	Name = CAPS "Scape - Stereo delay with chromatic resonances";
177 	autogen();
178 }
179 
180 /* //////////////////////////////////////////////////////////////////////// */
181 
182 void
init()183 DDDelay::init()
184 {
185 	float l = 2*fs; /* one beat at 30 bpm */
186 	for(int i=0; i<4; ++i)
187 	{
188 		step[i].delay.init((int) (l + .5));
189 		step[i].lp.set(.001);
190 	}
191 }
192 
193 void
activate()194 DDDelay::activate()
195 {
196 	for(int i=0; i<4; ++i)
197 	{
198 		step[i].delay.reset();
199 		step[i].lp.reset();
200 	}
201 }
202 
203 void
cycle(uint frames)204 DDDelay::cycle (uint frames)
205 {
206 	/* delay times */
207 	int div = (int) getport(1);
208 	int t = -1 + (int) (60*fs/getport(0));
209 
210 	sample_t * s = ports[2];
211 	sample_t * d = ports[3];
212 
213 	sample_t g[4] = {.4,.7,.8,.7};
214 	for(uint i=0; i<frames; ++i)
215 	{
216 		sample_t x=s[i], y=x;
217 
218 		for(int j=0; j<div; ++j)
219 		{
220 			step[j].delay.put(y);
221 			y = step[j].delay[t];
222 			x += g[j]*y;
223 		}
224 
225 		d[i] = x;
226 	}
227 }
228 
229 /* //////////////////////////////////////////////////////////////////////// */
230 
231 PortInfo
232 DDDelay::port_info [] =
233 {
234 	{ "bpm", CTRL_IN, {DEFAULT_MID, 30, 182} },
235 	{	"div", CTRL_IN, {INTEGER | DEFAULT_HIGH, 2, 4},
236 		"{2:'♪♪',3:'♪♪♪',4:'♬♬'}" },
237 
238 	{ "in", AUDIO_IN },
239 	{ "out", AUDIO_OUT },
240 };
241 
242 template <> void
setup()243 Descriptor<DDDelay>::setup()
244 {
245 	Label = "DDDelay";
246 	Name = CAPS "DDDelay - Delay with fixed repetition count";
247 	autogen();
248 }
249 
250