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