1 /*
2 Scape.cc
3
4 Copyright 2004-7 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 2
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 void
activate()32 Scape::activate()
33 {
34 time = 0;
35 fb = 0;
36
37 for (int i = 0; i < 4; ++i)
38 svf[i].reset(),
39 svf[i].set_out (SVF::Band),
40 hipass[i].set_f (250. / fs);
41 svf[3].set_out (SVF::Low),
42
43 delay.reset();
44 period = 0;
45 }
46
47 static double
48 dividers [] = {
49 1 /* 0 sentinel */,
50 1, 0.5, 0.66666666666666666667, 0.75
51 };
52
53 float
frandom2()54 frandom2()
55 {
56 float f = frandom();
57 return f * f * f;
58 }
59
60 template <sample_func_t F>
61 void
one_cycle(int frames)62 Scape::one_cycle (int frames)
63 {
64 sample_t * s = ports[0];
65
66 // double one_over_n = 1 / (double) frames;
67
68 /* delay times */
69 double t1 = fs * 60. / getport(1);
70 int div = (int) getport(2);
71 double t2 = t1 * dividers[div];
72
73 fb = getport(3);
74
75 double dry = getport(4);
76 dry = dry * dry;
77 double blend = getport(5);
78
79 sample_t * dl = ports[6];
80 sample_t * dr = ports[7];
81
82 DSP::FPTruncateMode truncate;
83
84 while (frames)
85 {
86 /* flip 'renormal' addition constant */
87 normal = -normal;
88
89 /* retune filters */
90 if (period <= 1)
91 {
92 period = t2 * .5;
93 float f, q;
94
95 f = frandom2();
96 svf[0].set_f_Q (300 + 300 * f / fs, .3);
97 svf[3].set_f_Q (300 + 600 * 2 * f / fs, .6);
98
99 f = frandom2();
100 q = f;
101 svf[1].set_f_Q (400 + 2400 * f / fs, q);
102 q = 1 - f;
103 svf[2].set_f_Q (400 + 2400 * f / fs, q);
104 }
105
106 int n = min ((int) period, frames);
107 if (n < 1)
108 {
109 /* not reached */
110 #ifdef DEBUG
111 fprintf (stderr, "Scape: %d - %d/%d frames, t2 = %.3f?!?\n", (int) period, n, frames, t2);
112 #endif
113 return;
114 }
115
116 /* sample loop */
117 for (int i = 0; i < n; ++i)
118 {
119 sample_t x = s[i] + normal;
120
121 sample_t x1 = delay.get_at (t1);
122 sample_t x2 = delay.get_at (t2);
123
124 delay.put (x + fb * x1 + normal);
125 x = dry * x + .2 * svf[0].process (x) + .6 * svf[3].process(x);
126
127 x1 = svf[1].process (x1 - normal);
128 x2 = svf[2].process (x2 - normal);
129
130 x1 = hipass[1].process (x1);
131 x2 = hipass[2].process (x2);
132
133 sample_t x1l, x1r, x2l, x2r;
134 x1l = fabs (lfo[0].get());
135 x1r = 1 - x1l;
136 x2r = fabs (lfo[1].get());
137 x2l = 1 - x2r;
138
139 F (dl, i, x + blend * (x1 * x1l + x2 * x2l), adding_gain);
140 F (dr, i, x + blend * (x2 * x2r + x1 * x1r), adding_gain);
141 }
142
143 frames -= n;
144 period -= n;
145 s += n;
146 dl += n;
147 dr += n;
148 }
149 }
150
151 /* //////////////////////////////////////////////////////////////////////// */
152
153 PortInfo
154 Scape::port_info [] =
155 {
156 {
157 "in",
158 INPUT | AUDIO,
159 {BOUNDED, -1, 1}
160 }, {
161 "bpm",
162 INPUT | CONTROL,
163 {BOUNDED | DEFAULT_LOW, 30, 240}
164 }, {
165 "divider",
166 INPUT | CONTROL,
167 {BOUNDED | INTEGER | DEFAULT_MIN, 2, 4}
168 }, {
169 "feedback",
170 INPUT | CONTROL,
171 {BOUNDED | DEFAULT_LOW, 0, 1}
172 }, {
173 "dry",
174 INPUT | CONTROL,
175 {BOUNDED | DEFAULT_LOW, 0, 1}
176 }, {
177 "blend",
178 INPUT | CONTROL,
179 {BOUNDED | DEFAULT_HIGH, 0, 1}
180 }, {
181 "out:l",
182 OUTPUT | AUDIO,
183 {0}
184 }, {
185 "out:r",
186 OUTPUT | AUDIO,
187 {0}
188 }
189 };
190
191 template <> void
setup()192 Descriptor<Scape>::setup()
193 {
194 UniqueID = 2588;
195 Label = "Scape";
196 Properties = HARD_RT;
197
198 Name = CAPS "Scape - Stereo delay + Filters";
199 Maker = "Tim Goetze <tim@quitte.de>";
200 Copyright = "GPL, 2004-7";
201
202 /* fill port info and vtable */
203 autogen();
204 }
205
206