├── .gitignore
├── README
├── gendy-ex1.pd
├── gendy-gui.pd
├── gendy~-help.pd
├── package.txt
└── src
├── breakpoint.cpp
├── breakpoint.h
├── gendy_waveform.cpp
├── gendy_waveform.h
├── gendy~.cpp
├── gendy~.h
├── log.cpp
├── log.h
├── splines.cpp
├── splines.h
├── types.h
├── util.cpp
└── util.h
/.gitignore:
--------------------------------------------------------------------------------
1 | pd-linux/
2 | *.swp
3 | tags
4 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | gendy~ for Pure Data and Max/MSP
2 |
3 | Author: Spencer Russell
4 |
5 | Gendy is an external for Pure Data and Max/MSP based on Iannis Xenakis'
6 | Dynamic Stochastic Synthesis.
7 |
8 | The library implementing DSS is decoupled from the Pure Data and Max/MSP
9 | external code, so it should be relatively easily embeddable in other projects.
10 |
11 | For an excellent explanation of DSS, see Sergio Luque's master's thesis:
12 | http://www.sergioluque.com/thesis.html
13 |
14 | One of the departures from cannonical DSS is the introduction of "target waveforms"
15 | that the breakpoints gravitate towards. Currently only sinusoidal and square waves
16 | are implemented, but implementing new waveforms is trivial, I just haven't done it
17 | yet.
18 |
--------------------------------------------------------------------------------
/gendy-ex1.pd:
--------------------------------------------------------------------------------
1 | #N canvas 4 278 1369 435 10;
2 | #X obj 163 35 gendy-gui;
3 | #X obj 547 393 dac~;
4 | #X obj 674 275 *~ 0.3;
5 | #X obj 164 267 *~ 0.3;
6 | #X obj 673 32 gendy-gui;
7 | #X connect 0 0 3 0;
8 | #X connect 0 1 4 0;
9 | #X connect 2 0 1 1;
10 | #X connect 3 0 1 0;
11 | #X connect 4 0 2 0;
12 |
--------------------------------------------------------------------------------
/gendy-gui.pd:
--------------------------------------------------------------------------------
1 | #N canvas 4 592 1369 398 10;
2 | #X obj 552 303 gendy~;
3 | #X obj 298 219 hsl 128 15 50 2000 1 0 \$0-freq \$0-freq_in Freq -2
4 | -8 0 10 -262144 -1 -1 3786 1;
5 | #X msg 527 153 h_pull \$1;
6 | #X msg 706 153 v_pull \$1;
7 | #X msg 618 154 h_step \$1;
8 | #X msg 804 153 v_step \$1;
9 | #X msg 981 152 breakpoints \$1;
10 | #X floatatom 64 229 5 0 0 2 Breakpoints #0-breakpoints_in #0-breakpoints
11 | ;
12 | #N canvas 4 49 1369 186 (subpatch) 0;
13 | #X array \$0-waveform 1000 float 2;
14 | #X coords 0 1 1000 -1 150 100 1;
15 | #X restore 288 69 graph;
16 | #X obj 527 126 r \$0-h_pull;
17 | #X obj 618 128 r \$0-h_step;
18 | #X obj 706 125 r \$0-v_pull;
19 | #X obj 804 126 r \$0-v_step;
20 | #X obj 899 127 r \$0-freq;
21 | #X obj 980 125 r \$0-breakpoints;
22 | #X obj 551 336 outlet~;
23 | #X obj 810 27 inlet;
24 | #X obj 767 338 outlet;
25 | #X msg 899 154 freq \$1;
26 | #X obj 489 25 loadbang;
27 | #X obj 489 51 f \$0;
28 | #X obj 321 172 tgl 15 0 \$0-display \$0-display_in Display 20 7 0 10
29 | -262144 -1 -1 1 1;
30 | #X obj 1113 85 r \$0-display;
31 | #N canvas 4 251 1369 378 input 0;
32 | #X obj 145 303 s \$0-h_pull_in;
33 | #X obj 266 303 s \$0-h_step_in;
34 | #X obj 394 298 s \$0-v_pull_in;
35 | #X obj 510 292 s \$0-v_step_in;
36 | #X obj 638 292 s \$0-freq_in;
37 | #X obj 752 290 s \$0-breakpoints_in;
38 | #X obj 900 294 s \$0-display_in;
39 | #X obj 515 17 inlet;
40 | #X obj 515 42 route h_pull h_step v_pull v_step freq breakpoints display
41 | ;
42 | #X obj 918 64 route flat square sine;
43 | #X msg 918 86 flat;
44 | #X msg 968 88 square;
45 | #X msg 1021 87 sine;
46 | #X obj 1040 287 s \$0-waveshape_in;
47 | #X obj 1085 167 loadbang;
48 | #X msg 212 271 0.1;
49 | #X msg 324 274 0.5;
50 | #X msg 444 271 0.5;
51 | #X msg 559 262 0.5;
52 | #X msg 681 259 100;
53 | #X msg 769 261 7;
54 | #X msg 922 268 1;
55 | #X msg 1062 256 sine;
56 | #X obj 928 243 delay 100;
57 | #X connect 7 0 8 0;
58 | #X connect 8 0 0 0;
59 | #X connect 8 1 1 0;
60 | #X connect 8 2 2 0;
61 | #X connect 8 3 3 0;
62 | #X connect 8 4 4 0;
63 | #X connect 8 5 5 0;
64 | #X connect 8 6 6 0;
65 | #X connect 8 7 9 0;
66 | #X connect 9 0 10 0;
67 | #X connect 9 1 11 0;
68 | #X connect 9 2 12 0;
69 | #X connect 10 0 13 0;
70 | #X connect 11 0 13 0;
71 | #X connect 12 0 13 0;
72 | #X connect 14 0 22 0;
73 | #X connect 14 0 20 0;
74 | #X connect 14 0 19 0;
75 | #X connect 14 0 18 0;
76 | #X connect 14 0 17 0;
77 | #X connect 14 0 16 0;
78 | #X connect 14 0 15 0;
79 | #X connect 14 0 23 0;
80 | #X connect 15 0 0 0;
81 | #X connect 16 0 1 0;
82 | #X connect 17 0 2 0;
83 | #X connect 18 0 3 0;
84 | #X connect 19 0 4 0;
85 | #X connect 20 0 5 0;
86 | #X connect 21 0 6 0;
87 | #X connect 22 0 13 0;
88 | #X connect 23 0 21 0;
89 | #X restore 810 49 pd input;
90 | #N canvas 0 691 1375 186 waveshape 0;
91 | #X obj 31 31 cnv 15 68 88 empty empty Waveshape 3 9 0 12 -233017 -66577
92 | 0;
93 | #X obj 39 55 tgl 15 0 \$0-square \$0-square_in Square 17 7 0 10 -262144
94 | -1 -1 0 1;
95 | #X obj 39 75 tgl 15 0 \$0-sine \$0-sine_in Sine 17 7 0 10 -262144 -1
96 | -1 1 1;
97 | #X obj 39 95 tgl 15 0 \$0-flat \$0-flat_in Flat 17 7 0 10 -262144 -1
98 | -1 0 1;
99 | #X obj 283 139 r \$0-square;
100 | #X obj 280 248 r \$0-sine;
101 | #X obj 553 248 s \$0-sine_in;
102 | #X obj 280 353 r \$0-flat;
103 | #X obj 557 352 s \$0-flat_in;
104 | #X obj 552 167 s \$0-square_in;
105 | #X obj 283 161 select 1;
106 | #X msg 283 184 0;
107 | #X obj 280 274 select 1;
108 | #X msg 280 297 0;
109 | #X obj 280 380 select 1;
110 | #X msg 280 403 0;
111 | #X msg 379 68 1;
112 | #X msg 431 68 1;
113 | #X msg 484 70 1;
114 | #X msg 238 465 flat;
115 | #X msg 129 361 sine;
116 | #X msg 60 294 square;
117 | #X obj 130 550 s \$0-waveshape;
118 | #X obj 379 16 r \$0-waveshape_in;
119 | #X obj 379 39 route flat sine square;
120 | #X connect 4 0 10 0;
121 | #X connect 5 0 12 0;
122 | #X connect 7 0 14 0;
123 | #X connect 10 0 11 0;
124 | #X connect 10 0 21 0;
125 | #X connect 11 0 6 0;
126 | #X connect 11 0 8 0;
127 | #X connect 12 0 13 0;
128 | #X connect 12 0 20 0;
129 | #X connect 13 0 9 0;
130 | #X connect 13 0 8 0;
131 | #X connect 14 0 15 0;
132 | #X connect 14 0 19 0;
133 | #X connect 15 0 9 0;
134 | #X connect 15 0 6 0;
135 | #X connect 16 0 8 0;
136 | #X connect 17 0 6 0;
137 | #X connect 18 0 9 0;
138 | #X connect 19 0 22 0;
139 | #X connect 20 0 22 0;
140 | #X connect 21 0 22 0;
141 | #X connect 23 0 24 0;
142 | #X connect 24 0 16 0;
143 | #X connect 24 1 17 0;
144 | #X connect 24 2 18 0;
145 | #X coords 0 -1 1 1 70 90 2 30 30;
146 | #X restore 210 69 pd waveshape;
147 | #X obj 1218 145 r \$0-waveshape;
148 | #N canvas 4 719 1369 271 sliders 0;
149 | #X obj 11 11 cnv 15 140 140 empty empty empty 20 12 0 14 -233017 -66577
150 | 0;
151 | #X obj 16 27 hsl 128 15 0.001 1 1 0 \$0-h_pull \$0-h_pull_in h_pull
152 | -2 -8 0 10 -262144 -1 -1 8467 1;
153 | #X obj 17 62 hsl 128 15 0 1 0 0 \$0-v_pull \$0-v_pull_in v_pull -2
154 | -8 0 10 -262144 -1 -1 6350 1;
155 | #X obj 19 98 hsl 128 15 0 1 0 0 \$0-h_step \$0-h_step_in h_step -2
156 | -8 0 10 -262144 -1 -1 6350 1;
157 | #X obj 18 133 hsl 128 15 0 1 0 0 \$0-v_step \$0-v_step_in v_step -2
158 | -8 0 10 -262144 -1 -1 6350 1;
159 | #X coords 0 -1 1 1 142 142 2 10 10;
160 | #X restore 60 69 pd sliders;
161 | #X msg 1113 145 redraw;
162 | #X msg 489 81 table \$1-waveform;
163 | #X obj 1113 123 metro 75;
164 | #X msg 1183 124 display \$1;
165 | #X connect 0 0 15 0;
166 | #X connect 2 0 0 0;
167 | #X connect 2 0 17 0;
168 | #X connect 3 0 0 0;
169 | #X connect 3 0 17 0;
170 | #X connect 4 0 0 0;
171 | #X connect 4 0 17 0;
172 | #X connect 5 0 0 0;
173 | #X connect 5 0 17 0;
174 | #X connect 6 0 0 0;
175 | #X connect 6 0 17 0;
176 | #X connect 9 0 2 0;
177 | #X connect 10 0 4 0;
178 | #X connect 11 0 3 0;
179 | #X connect 12 0 5 0;
180 | #X connect 13 0 18 0;
181 | #X connect 14 0 6 0;
182 | #X connect 16 0 23 0;
183 | #X connect 18 0 17 0;
184 | #X connect 18 0 0 0;
185 | #X connect 19 0 20 0;
186 | #X connect 20 0 28 0;
187 | #X connect 22 0 29 0;
188 | #X connect 22 0 30 0;
189 | #X connect 25 0 0 0;
190 | #X connect 25 0 17 0;
191 | #X connect 27 0 0 0;
192 | #X connect 27 0 17 0;
193 | #X connect 28 0 0 0;
194 | #X connect 29 0 27 0;
195 | #X connect 30 0 17 0;
196 | #X coords 0 -1 1 1 400 200 1 50 50;
197 |
--------------------------------------------------------------------------------
/gendy~-help.pd:
--------------------------------------------------------------------------------
1 | #N canvas 374 166 999 740 10;
2 | #X obj 719 352 gendy~;
3 | #X msg 27 457 h_pull \$1;
4 | #X obj 707 406 dac~;
5 | #X obj 719 378 *~ 0.1;
6 | #X obj 30 438 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
7 | -1 -1 12700 1;
8 | #X obj 236 443 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
9 | -1 -1 12700 1;
10 | #X msg 233 462 v_pull \$1;
11 | #X obj 238 254 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
12 | -1 -1 9300 1;
13 | #X msg 235 273 v_step \$1;
14 | #X obj 29 255 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
15 | -1 -1 10600 1;
16 | #X msg 26 274 h_step \$1;
17 | #X obj 28 77 hsl 128 15 20 10000 1 0 empty empty empty -2 -8 0 10 -262144
18 | -1 -1 7300 1;
19 | #X msg 25 115 freq \$1;
20 | #X msg 239 123 breakpoints \$1;
21 | #N canvas 0 0 450 300 (subpatch) 0;
22 | #X array gendygraph 1024 float 2;
23 | #X coords 0 1 1023 -1 200 140 1;
24 | #X restore 686 146 graph;
25 | #X msg 449 487 redraw;
26 | #X msg 37 610 linear;
27 | #X msg 28 589 cubic;
28 | #X msg 250 627 sine;
29 | #X msg 263 648 square;
30 | #X msg 239 606 flat;
31 | #X obj 449 466 metro 75;
32 | #X obj 449 447 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
33 | 1;
34 | #X floatatom 25 97 5 0 0 0 - - -;
35 | #X obj 25 137 s gendy_con;
36 | #X obj 26 295 s gendy_con;
37 | #X obj 235 294 s gendy_con;
38 | #X obj 27 478 s gendy_con;
39 | #X obj 233 483 s gendy_con;
40 | #X obj 448 190 s gendy_con;
41 | #X obj 449 508 s gendy_con;
42 | #X obj 239 671 s gendy_con;
43 | #X obj 28 632 s gendy_con;
44 | #X obj 719 326 r gendy_con;
45 | #X obj 448 145 loadbang;
46 | #X obj 239 145 s gendy_con;
47 | #X text 677 456 gendy~;
48 | #X text 676 481 A Dynamic Stochastic Synthesis external;
49 | #X text 22 21 freq N;
50 | #X text 22 43 Sets the average waveform;
51 | #X text 22 56 frequency to N;
52 | #X text 26 185 h_step N;
53 | #X text 26 208 Varies the horizontal;
54 | #X text 25 223 stepsize of the;
55 | #X text 26 236 breakpoints (0-1);
56 | #X text 233 219 stepsize of the;
57 | #X text 235 232 breakpoints (0-1);
58 | #X text 235 184 v_step N;
59 | #X text 235 207 Varies the vertical;
60 | #X text 24 345 h_pull N;
61 | #X text 24 368 Varies how strongly;
62 | #X text 24 392 pulled towards its;
63 | #X text 24 380 each breakpoint is;
64 | #X text 24 405 center point;
65 | #X text 25 417 horizontally;
66 | #X text 231 345 h_pull N;
67 | #X text 231 368 Varies how strongly;
68 | #X text 231 392 pulled towards its;
69 | #X text 231 380 each breakpoint is;
70 | #X text 231 405 center point;
71 | #X text 232 417 vertically;
72 | #X text 25 521 cubic \, linear;
73 | #X text 24 544 Sets the interpolation;
74 | #X text 25 556 method;
75 | #X text 231 527 flat \, sine \, square;
76 | #X text 230 550 Sets the waveshape;
77 | #X text 230 562 that the breakpoints;
78 | #X text 230 575 gravitate towards;
79 | #X text 236 27 breakpoints N;
80 | #X text 236 49 Sets the number of;
81 | #X text 236 62 breakpoints;
82 | #X text 445 81 table NAME;
83 | #X text 446 102 Selects a table to;
84 | #X text 446 114 display the waveform;
85 | #X text 446 339 redraw;
86 | #X text 447 361 Refreshes the waveform;
87 | #X text 446 374 display;
88 | #X obj 449 401 loadbang;
89 | #X msg 449 421 1;
90 | #X text 676 506 This synthesizer creates a waveform by;
91 | #X text 676 518 interpolating a series of breakpoints \,;
92 | #X text 676 531 each of which moves in a 2-dimensional;
93 | #X text 676 543 random walk;
94 | #X obj 239 83 hradio 15 1 0 10 empty empty empty 0 -8 0 10 -262144
95 | -1 -1 6;
96 | #X obj 239 102 + 1;
97 | #X msg 448 168 table gendygraph;
98 | #X connect 0 0 3 0;
99 | #X connect 1 0 27 0;
100 | #X connect 3 0 2 0;
101 | #X connect 3 0 2 1;
102 | #X connect 4 0 1 0;
103 | #X connect 5 0 6 0;
104 | #X connect 6 0 28 0;
105 | #X connect 7 0 8 0;
106 | #X connect 8 0 26 0;
107 | #X connect 9 0 10 0;
108 | #X connect 10 0 25 0;
109 | #X connect 11 0 23 0;
110 | #X connect 12 0 24 0;
111 | #X connect 13 0 35 0;
112 | #X connect 15 0 30 0;
113 | #X connect 16 0 32 0;
114 | #X connect 17 0 32 0;
115 | #X connect 18 0 31 0;
116 | #X connect 19 0 31 0;
117 | #X connect 20 0 31 0;
118 | #X connect 21 0 15 0;
119 | #X connect 22 0 21 0;
120 | #X connect 23 0 12 0;
121 | #X connect 33 0 0 0;
122 | #X connect 34 0 85 0;
123 | #X connect 77 0 78 0;
124 | #X connect 78 0 22 0;
125 | #X connect 83 0 84 0;
126 | #X connect 84 0 13 0;
127 | #X connect 85 0 29 0;
128 |
--------------------------------------------------------------------------------
/package.txt:
--------------------------------------------------------------------------------
1 | #
2 | # this file contains info for the flext build system
3 | #
4 | NAME=gendy~
5 | SRCDIR=src
6 | SRCS= breakpoint.cpp \
7 | gendy~.cpp \
8 | gendy_waveform.cpp \
9 | log.cpp \
10 | splines.cpp \
11 | util.cpp
12 |
13 | HDRS= breakpoint.h \
14 | gendy~.h \
15 | gendy_waveform.h \
16 | log.h \
17 | splines.h \
18 | util.h
19 |
--------------------------------------------------------------------------------
/src/breakpoint.cpp:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #include "breakpoint.h"
31 | #include "log.h"
32 | #include
33 | #include "util.h"
34 |
35 | breakpoint::breakpoint() {
36 | print_log("gendy~: New breakpoint with default args", LOG_DEBUG);
37 | duration = 0;
38 | amplitude = 0;
39 | center_dur = 0;
40 | center_amp = 0;
41 | }
42 |
43 | breakpoint::breakpoint(gendydur_t duration, gendyamp_t amplitude) {
44 | print_log("gendy~: New breakpoint with duration %u", duration, LOG_DEBUG);
45 | print_log("gendy~: \t\t\tamplitude %f", amplitude, LOG_DEBUG);
46 | this->duration = duration;
47 | this->amplitude = amplitude;
48 | }
49 |
50 | breakpoint::breakpoint(gendydur_t duration, gendyamp_t amplitude,
51 | gendydur_t center_dur, gendyamp_t center_amp) {
52 | print_log("gendy~: New breakpoint with duration %u", duration, LOG_DEBUG);
53 | print_log("gendy~: \t\t\tamplitude %f", amplitude, LOG_DEBUG);
54 | print_log("gendy~: \t\t\tcenter_dur %u", center_dur, LOG_DEBUG);
55 | print_log("gendy~: \t\t\tcenter_amp %f", center_amp, LOG_DEBUG);
56 | this->duration = duration;
57 | this->amplitude = amplitude;
58 | this->center_dur = center_dur;
59 | this->center_amp = center_amp;
60 | }
61 |
62 | // elastic_move
63 | //
64 | // elastic_move sets a new position for the breakpoint. The breakpoint is
65 | // moved (vertically and horizontally) from its current position by a normal
66 | // distributed distance, the standard deviations of which are h_step and
67 | // v_step.
68 | //
69 | // the breakpoint is also pulled toward its center by the factors h_pull and
70 | // v_pull, with a 1 corresponding to immediately jumping to the center point
71 | // and 0 not pulling toward the center point at all.
72 | //
73 | // amplitudes out of the audio range [-1,1] are mirrored back in.
74 | // durations less than 2 samples are set to 2.
75 | //
76 | void breakpoint::elastic_move(gendydur_t h_step, gendyamp_t v_step,
77 | gendydur_t h_pull, gendyamp_t v_pull) {
78 | gendydur_t old_duration = duration;
79 | gendydur_t new_duration;
80 | gendyamp_t new_amplitude;
81 |
82 | new_duration = old_duration *
83 | pow(center_dur / old_duration,h_pull * h_step) *
84 | exp(gauss() *0.1 * h_step * (1.0-h_pull));
85 | /*new_duration = old_duration + round((1.0 - h_pull) * h_step * gauss() +
86 | (h_pull * (center_dur - old_duration))); */
87 | // set boundaries on new_duration
88 | if(new_duration < 2)
89 | new_duration = 2;
90 |
91 | new_amplitude = amplitude + v_step *
92 | (v_pull * (center_amp - amplitude) +
93 | (1.0 - v_pull) * gauss());
94 | /*new_amplitude = amplitude + (1 - v_pull) * v_step * gauss() +
95 | v_pull * (center_amp - amplitude);*/
96 | // set mirror boundaries on new_amplitude
97 | do {
98 | if(new_amplitude > 1)
99 | new_amplitude = 2 - new_amplitude;
100 | if(new_amplitude < -1)
101 | new_amplitude = -2 - new_amplitude;
102 | } while (new_amplitude < -1 || new_amplitude > 1);
103 |
104 | duration = new_duration;
105 | amplitude = new_amplitude;
106 | }
107 |
108 | void breakpoint::set_duration(gendydur_t new_duration) {
109 | duration = new_duration;
110 | }
111 |
112 | void breakpoint::set_amplitude(gendyamp_t new_amplitude) {
113 | amplitude = new_amplitude;
114 | }
115 |
116 | void breakpoint::set_position(gendydur_t new_duration, gendyamp_t new_amplitude) {
117 | //TODO: argument sanitization
118 | duration = new_duration;
119 | amplitude = new_amplitude;
120 | }
121 |
122 | void breakpoint::set_center_duration(gendydur_t new_duration) {
123 | center_dur = new_duration;
124 | }
125 |
126 | void breakpoint::set_center_amplitude(gendyamp_t new_amplitude) {
127 | center_amp = new_amplitude;
128 | }
129 |
130 | // set_center
131 | // accessor function to set the amplitude and duration of a breakpoint's
132 | // center position
133 |
134 | void breakpoint::set_center(gendydur_t new_duration, gendyamp_t new_amplitude) {
135 | //TODO: argument sanitization
136 | center_dur= new_duration;
137 | center_amp = new_amplitude;
138 | }
139 |
140 | gendydur_t breakpoint::get_duration() const {
141 | return duration;
142 | }
143 |
144 | gendyamp_t breakpoint::get_amplitude() const {
145 | return amplitude;
146 | }
147 |
148 | gendydur_t breakpoint::get_center_duration() const {
149 | return center_dur;
150 | }
151 |
152 | gendyamp_t breakpoint::get_center_amplitude() const {
153 | return center_amp;
154 | }
155 |
--------------------------------------------------------------------------------
/src/breakpoint.h:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #ifndef BREAKPOINT_H
31 | #define BREAKPOINT_H
32 |
33 | #include "types.h"
34 |
35 | class breakpoint
36 | {
37 | // store current breakpoint location
38 | // duration is in samples
39 | gendyamp_t amplitude;
40 | gendydur_t duration;
41 |
42 | // store the center point the breakpoint gravitates to
43 | gendyamp_t center_amp;
44 | gendydur_t center_dur;
45 |
46 | public:
47 | breakpoint();
48 | breakpoint(gendydur_t duration, gendyamp_t amplitude);
49 | breakpoint(gendydur_t duration, gendyamp_t amplitude,
50 | gendydur_t center_dur, gendyamp_t center_amp);
51 | void elastic_move(gendydur_t h_step, gendyamp_t v_step,
52 | gendydur_t h_pull, gendyamp_t v_pull);
53 | void set_duration(gendydur_t new_duration);
54 | void set_amplitude(gendyamp_t new_amplitude);
55 | void set_position(gendydur_t new_duration, gendyamp_t new_amplitude);
56 | void set_center_duration(gendydur_t new_duration);
57 | void set_center_amplitude(gendyamp_t new_amplitude);
58 | void set_center(gendydur_t new_duration, gendyamp_t new_amplitude);
59 | gendydur_t get_duration() const;
60 | gendyamp_t get_amplitude() const;
61 | gendydur_t get_center_duration() const;
62 | gendyamp_t get_center_amplitude() const;
63 | };
64 | #endif /* BREAKPOINT_H */
65 |
--------------------------------------------------------------------------------
/src/gendy_waveform.cpp:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #include "gendy_waveform.h"
31 | #include "log.h"
32 | #include "splines.h"
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | using namespace std;
39 |
40 | // gendy_waveform class constructor with all default arguments
41 | gendy_waveform::gendy_waveform() {
42 | //initialize variables to defaults
43 | step_width = 0.1;
44 | step_height = 0.1;
45 | duration_pull = 0.7;
46 | amplitude_pull = 0.4;
47 | constrain_endpoints = true;
48 |
49 | // start with a single breakpoint that spans the whole wavelength
50 | breakpoint_list.push_front(breakpoint(147,0,147,0));
51 | // and add an guard point to the end (for linear interpolation)
52 | breakpoint_list.push_back(breakpoint(147,0,147,0));
53 | // no pre-guard points
54 | breakpoint_begin = breakpoint_list.begin();
55 | breakpoint_current = breakpoint_list.begin();
56 | // 1 end guard point, which acts as the end of the list of actual
57 | // breakpoints
58 | breakpoint_end = --breakpoint_list.end();
59 |
60 | set_interpolation(CUBIC);
61 |
62 | // set the average wavelength for 300 Hz at 44.1 kHz
63 | set_avg_wavelength(147);
64 | waveshape = FLAT;
65 | phase = 0;
66 |
67 |
68 | set_num_breakpoints(8);
69 | reset_breakpoints();
70 | move_breakpoints();
71 | }
72 |
73 | gendy_waveform::~gendy_waveform() {
74 | }
75 |
76 | //TODO: protect against this getting called before data
77 | //strucutres are set up
78 | void gendy_waveform::set_num_breakpoints(int new_size) {
79 | if(new_size <= 0) {
80 | print_log("gendy~: Cannot resize to less than 1, resizing to 1", LOG_INFO);
81 | new_size = 1;
82 | }
83 |
84 | unsigned int target_length = new_size + get_num_guardpoints();
85 |
86 | while(breakpoint_list.size() < (target_length))
87 | add_breakpoint();
88 | while(breakpoint_list.size() > (target_length))
89 | remove_breakpoint();
90 | center_breakpoints();
91 | }
92 |
93 | void gendy_waveform::set_avg_wavelength(float new_wavelength) {
94 | average_wavelength = new_wavelength;
95 | center_breakpoints();
96 | }
97 |
98 |
99 | unsigned int gendy_waveform::get_num_guardpoints() const {
100 | return breakpoint_list.size() - get_num_breakpoints();
101 | }
102 |
103 | unsigned int gendy_waveform::get_num_breakpoints() const {
104 | list::const_iterator i = breakpoint_begin;
105 | unsigned int num_breakpoints = 0;
106 | while(i != breakpoint_end) {
107 | ++i;
108 | ++num_breakpoints;
109 | }
110 | return num_breakpoints;
111 | }
112 |
113 | void gendy_waveform::set_pre_guardpoints(unsigned int guardpoints) {
114 | list::iterator src = breakpoint_end;
115 | list::iterator i = breakpoint_begin;
116 | //work backwards from the first breakpoint until:
117 | // a) we get to the beginning of the list (more guard points needed)
118 | // b) guardpoints goes to 0 (we need to remove guardpoints)
119 | // c) both (we have the proper number of guardpoints)
120 | //we keep track of src because that's where we'll start copying
121 | //guard points from
122 | while(guardpoints && i != breakpoint_list.begin()) {
123 | --guardpoints;
124 | --i;
125 | --src;
126 | }
127 | //if we're not at the beginning of the list yet, delete guard points
128 | while(i != breakpoint_list.begin())
129 | breakpoint_list.pop_front();
130 | //if guardpoints hasn't run out yet, we need some more. copy them.
131 | while(guardpoints--)
132 | breakpoint_list.push_front(*(src--));
133 | }
134 |
135 | void gendy_waveform::set_post_guardpoints(unsigned int guardpoints) {
136 | list::iterator src = breakpoint_begin;
137 | // move breakpoint_end to point at the last breakpoint instead
138 | // of the first node after the last breakpoint, so it doesn't
139 | // get clobbered
140 | --breakpoint_end;
141 | list::iterator i = breakpoint_end;
142 | //work forwards from the last breakpoint until:
143 | // a) we get to the end of the list (more guard points needed)
144 | // b) guardpoints goes to 0 (we need to remove guardpoints)
145 | // c) both (we have the proper number of guardpoints)
146 | //we keep track of src because that's where we'll start copying
147 | //guard points from
148 | while(guardpoints && i != --breakpoint_list.end()) {
149 | --guardpoints;
150 | ++i;
151 | ++src;
152 | }
153 | //if we're not at the beginning of the list yet, delete guard points
154 | while(i != --breakpoint_list.end())
155 | breakpoint_list.pop_back();
156 | //if guardpoints hasn't run out yet, we need some more. copy them.
157 | while(guardpoints--)
158 | breakpoint_list.push_back(*(src++));
159 | //now we put breakpoint_end back where it's supposed to be
160 | ++breakpoint_end;
161 | }
162 |
163 | void gendy_waveform::set_interpolation(interpolation_t new_interpolation) {
164 | if(new_interpolation == LINEAR) {
165 | interpolation_type = LINEAR;
166 | set_pre_guardpoints(0);
167 | set_post_guardpoints(1);
168 | }
169 | else if(new_interpolation == CUBIC) {
170 | interpolation_type = CUBIC;
171 | set_pre_guardpoints(1);
172 | set_post_guardpoints(2);
173 | }
174 | else {
175 | print_log("gendy~: unimplemented interpolation. defaulting to linear",
176 | LOG_ERROR);
177 | }
178 | }
179 |
180 | /*
181 | void gendy_waveform::set_interpolation_type(t_symbol *new_interpolation) {
182 | if(strcmp(GetString(new_interpolation), "linear") == 0)
183 | interpolation_type = LINEAR;
184 | else
185 | post("So far only linear interpolation implemented.");
186 | } */
187 |
188 | void gendy_waveform::set_waveshape(waveshape_t new_waveshape) {
189 | waveshape = new_waveshape;
190 | center_breakpoints();
191 | }
192 |
193 | void gendy_waveform::set_step_width(float new_width) {
194 | step_width = new_width;
195 | }
196 |
197 | void gendy_waveform::set_step_height(float new_height) {
198 | step_height = new_height;
199 | }
200 |
201 | void gendy_waveform::set_duration_pull(float new_pull) {
202 | duration_pull = new_pull;
203 | }
204 |
205 | void gendy_waveform::set_amplitude_pull(float new_pull) {
206 | amplitude_pull = new_pull;
207 | }
208 |
209 | void gendy_waveform::set_constrain_endpoints(bool constrain) {
210 | constrain_endpoints = constrain;
211 | }
212 |
213 | float gendy_waveform::get_wavelength() const {
214 | list::iterator i;
215 | float wavelength = 0;
216 | for(i = breakpoint_begin; i != breakpoint_end; i++)
217 | wavelength += i->get_duration();
218 | return wavelength;
219 | }
220 |
221 | // set new positions for all the breakpoints
222 | void gendy_waveform::move_breakpoints() {
223 | int breakpoint_count;
224 |
225 | // first we copy the last breakpoints of the current cycle into
226 | // the pre guard points, which represent the past
227 |
228 | list::iterator i = breakpoint_begin;
229 | list::iterator j = breakpoint_end;
230 | while(i != breakpoint_list.begin())
231 | *(--i) = *(--j);
232 |
233 | // now we copy the post guard points (which represent the first
234 | // breakpoints of the next cycle) into the beginning of this cycle
235 | i = breakpoint_begin;
236 | j = breakpoint_end;
237 | while(j != breakpoint_list.end())
238 | *(i++) = *(j++);
239 | // i now points to the first breakpoint that needs to be newly calculated.
240 | // we'll also continue into the post guard points and recalculate those,
241 | // they are the future
242 |
243 |
244 | // calculate new values for all the rest of the breakpoints
245 | while(i != breakpoint_list.end()) {
246 | i->elastic_move(step_width, step_height, duration_pull, amplitude_pull);
247 | i++;
248 | }
249 | }
250 |
251 | // adds a breakpoint by splitting the longest breakpoint into two
252 | void gendy_waveform::add_breakpoint() {
253 | gendydur_t new_duration;
254 | gendyamp_t new_amplitude;
255 |
256 | gendydur_t longest_dur = 0;
257 | list::iterator longest_dur_breakpoint;
258 | list::iterator breakpoint_iter;
259 |
260 | // find the longest breakpoint
261 | for(breakpoint_iter = breakpoint_begin;
262 | breakpoint_iter != breakpoint_end;
263 | breakpoint_iter++) {
264 | if((breakpoint_iter->get_duration()) > longest_dur) {
265 | longest_dur = breakpoint_iter->get_duration();
266 | longest_dur_breakpoint = breakpoint_iter;
267 | }
268 | }
269 |
270 | // set the duration of the new breakpoint to be half the previous
271 | new_duration = longest_dur_breakpoint->get_duration() / 2;
272 | // halve the duration of the previous breakpoint
273 | longest_dur_breakpoint->set_duration(new_duration);
274 | // set the new amplitude to be the average of the 2 adjacent breakpoints
275 | // and move longest_dur_breakpoint iterator to the next breakpoint
276 | // for insertion
277 | new_amplitude = (longest_dur_breakpoint->get_amplitude() +
278 | (++longest_dur_breakpoint)->get_amplitude()) / 2;
279 | // insert the breakpoint in the list
280 | breakpoint_list.insert(longest_dur_breakpoint,
281 | breakpoint(new_duration, new_amplitude));
282 | //TODO: copy data to guard points if need be
283 | }
284 |
285 | // remove the breakpoint closest to its neighbors. breakpoints centers
286 | // should be reset after.
287 | void gendy_waveform::remove_breakpoint() {
288 | // start smallest_space to be the largest it can be
289 | gendydur_t smallest_space = numeric_limits::max();
290 | gendydur_t space;
291 | list::iterator smallest_space_position = breakpoint_list.end();
292 |
293 | // find the breakpoint closest to the adjacent breakpoints
294 | list::iterator breakpoint_iter = breakpoint_begin;
295 | list::iterator breakpoint_last = breakpoint_end;
296 | --breakpoint_last;
297 | while(breakpoint_iter != breakpoint_last) {
298 | space = breakpoint_iter->get_duration() +
299 | (++breakpoint_iter)->get_duration();
300 | if(space < smallest_space) {
301 | smallest_space = space;
302 | smallest_space_position = breakpoint_iter;
303 | }
304 | }
305 | if(smallest_space_position != breakpoint_list.end()) {
306 | // if the element we're about to erase is the current one
307 | if(breakpoint_current == smallest_space_position) {
308 | --breakpoint_current;
309 | phase += breakpoint_current->get_duration();
310 | }
311 | // erase returns the list element following the erased one
312 | smallest_space_position = breakpoint_list.erase(smallest_space_position);
313 | // add the erased breakpoint's duration to the previous breakpoint
314 | (--smallest_space_position)->set_duration(smallest_space);
315 | //TODO: update guard points if need be
316 | }
317 | }
318 |
319 | // center_breakpoints() calculates center positions for all the breakpoints
320 | // TODO: sawtooth and triangle
321 | // TODO: crashes when called on empty breakpoint list
322 | void gendy_waveform::center_breakpoints() {
323 | gendydur_t new_dur;
324 | gendyamp_t new_amp;
325 |
326 | list::iterator breakpoint_iter = breakpoint_begin;
327 | unsigned int breakpoint_index = 0;
328 | unsigned int num_breakpoints = get_num_breakpoints();
329 | while(breakpoint_iter != breakpoint_end) {
330 | // evenly distribute the breakpoints along the waveform
331 | breakpoint_iter->set_center_duration(average_wavelength / num_breakpoints);
332 |
333 | float t = (breakpoint_index) / (float)num_breakpoints;
334 | if(waveshape == FLAT)
335 | breakpoint_iter->set_center_amplitude(0);
336 | else if(waveshape == SINE)
337 | breakpoint_iter->set_center_amplitude(sin(2 * M_PI * t));
338 | else if(waveshape == SQUARE)
339 | breakpoint_iter->set_center_amplitude(t < 0.5 ? 1 : -1);
340 | breakpoint_iter++;
341 | breakpoint_index++;
342 | }
343 |
344 | // copy center data starting at the end of the actual breakpoints
345 | // into the beginning guard points
346 | list::iterator i = breakpoint_begin;
347 | list::iterator j = breakpoint_end;
348 | while(i != breakpoint_list.begin())
349 | *(--i) = *(--j);
350 |
351 | // copy center data starting at the beginning of the actual breakpoints
352 | // into the end guard points
353 | i = breakpoint_begin;
354 | j = breakpoint_end;
355 | while(j != breakpoint_list.end())
356 | *(j++) = *(i++);
357 | }
358 |
359 | // reset_breakpoints() sets all of the breakpoint positions to be the
360 | // center positions
361 | void gendy_waveform::reset_breakpoints() {
362 | list::iterator current;
363 | for(current = breakpoint_list.begin();
364 | current != breakpoint_list.end(); current++)
365 | current->set_position(current->get_center_duration(),
366 | current->get_center_amplitude());
367 | }
368 |
369 |
370 | /*
371 | * generates a block of gendy audio.
372 | * This function will take care of moving the breakpoints when it reaches
373 | * the end of a cycle.
374 | */
375 | //TODO: should this really return the number of samples copied? it's always
376 | // bufsize
377 | unsigned int gendy_waveform::get_block(gendysamp_t *dest, unsigned int bufsize) {
378 | if(interpolation_type == LINEAR) {
379 | // assert that we have no pre guard points and at least 1 post guard point
380 | assert(breakpoint_begin == breakpoint_list.begin());
381 | assert(breakpoint_end != breakpoint_list.end());
382 | // generate the endpoints for the current segment
383 | list::iterator breakpoint_next = breakpoint_current;
384 | breakpoint_next++;
385 | gendydur_t current_dur = breakpoint_current->get_duration();
386 | gendydur_t current_amp = breakpoint_current->get_amplitude();
387 | gendydur_t next_dur = breakpoint_next->get_duration();
388 | gendydur_t next_amp = breakpoint_next->get_amplitude();
389 |
390 | for(unsigned int i = 0; i < bufsize; i++) {
391 | dest[i] = current_amp + phase / current_dur * (next_amp - current_amp);
392 | phase++;
393 | // if we've reached the end of the current segment
394 | if(phase > current_dur) {
395 | breakpoint_current = breakpoint_next;;
396 | breakpoint_next++;
397 | phase -= current_dur;
398 | current_dur = next_dur;
399 | current_amp = next_amp;
400 | // if we've reached the end of this cycle
401 | if(breakpoint_next == breakpoint_end) {
402 | move_breakpoints();
403 | // wrap around the current and next iterators to the beginning
404 | breakpoint_current = breakpoint_begin;
405 | breakpoint_next = breakpoint_begin;
406 | breakpoint_next++;
407 | }
408 | next_dur = breakpoint_next->get_duration();
409 | next_amp = breakpoint_next->get_amplitude();
410 | }
411 | }
412 | }
413 | else if(interpolation_type == CUBIC) {
414 | double x[4];
415 | double y[4];
416 | double coefs[4];
417 | // set iter to be the breakpoint before the current one
418 | list::const_iterator iter = breakpoint_current;
419 | --iter;
420 | //collect the 4 points needed to interpolate in the first segment
421 | //x[0] will be negative enough to make x[1]=0, the beginning of
422 | //the segment we're actually interested in here
423 | x[0] = -iter->get_duration();
424 | y[0] = iter->get_amplitude();
425 | for(int i = 1; i < 4; i++) {
426 | x[i] = x[i-1] + iter->get_duration();
427 | ++iter;
428 | y[i] = iter->get_amplitude();
429 | }
430 | //iter is now pointing at the 4th point of this set
431 |
432 | get_cspline_coefs(x,y,coefs);
433 |
434 | for(unsigned int i = 0; i < bufsize; i++) {
435 | dest[i] = cspline_interp(coefs,phase);
436 | ++phase;
437 | //if we're past the end of the segment
438 | if(phase > x[2]) {
439 | ++breakpoint_current;
440 | phase -= x[2];
441 | // if we've reached the end of the current cycle
442 | if(breakpoint_current == breakpoint_end) {
443 | move_breakpoints();
444 | breakpoint_current = breakpoint_begin;
445 | }
446 | iter = breakpoint_current;
447 | --iter;
448 | x[0] = -iter->get_duration();
449 | y[0] = iter->get_amplitude();
450 | for(int i = 1; i < 4; i++) {
451 | x[i] = x[i-1] + iter->get_duration();
452 | ++iter;
453 | y[i] = iter->get_amplitude();
454 | }
455 | get_cspline_coefs(x,y,coefs);
456 | }
457 | }
458 | }
459 | else {
460 | print_log("gendy~: Unimplemeted Interpolation Type", LOG_ERROR);
461 | assert(0);
462 | }
463 | return bufsize;
464 | }
465 |
466 | //TODO:needs protection against buffer overrun
467 | unsigned int gendy_waveform::get_cycle(gendysamp_t *dest, unsigned int bufsize) const {
468 | if(interpolation_type == LINEAR) {
469 | assert(get_num_guardpoints() == 1);
470 |
471 | // we'll be going through the waveform piecewise. next stores
472 | // the endpoint of the current section
473 | list::const_iterator next = breakpoint_list.begin();
474 | // keep track of how long before a sample boundry the current
475 | // segment started. the first segment will start at the beginning of the buffer
476 | gendydur_t segment_shift = 0;
477 | gendydur_t current_dur, next_dur;
478 | gendyamp_t current_amp, next_amp;
479 | double slope;
480 | current_dur = next->get_duration();
481 | current_amp = next->get_amplitude();
482 |
483 | unsigned int buffer_offset = 0;
484 | // for each breakpoint
485 | while(++next != breakpoint_list.end()) {
486 | next_amp = next->get_amplitude();
487 | slope = (next_amp - current_amp) / current_dur;
488 | unsigned int i = 0;
489 | while(i + segment_shift < current_dur && i + buffer_offset < bufsize) {
490 | dest[i + buffer_offset] = current_amp +
491 | slope * (i + segment_shift);
492 | i++;
493 | }
494 | buffer_offset += i;
495 | segment_shift = (gendydur_t)i + segment_shift - current_dur;
496 | current_dur = next->get_duration();
497 | current_amp = next_amp;
498 | }
499 | return buffer_offset;
500 | }
501 | else if(interpolation_type == CUBIC) {
502 | assert(get_num_guardpoints() == 3);
503 | double x[4];
504 | double y[4];
505 | double coefs[4];
506 | double x_in = 0;
507 | // set iter to be the first guard breakpoint
508 | list::const_iterator iter = breakpoint_begin;
509 | --iter;
510 | //collect the 4 points needed to interpolate in the first segment
511 | //x[0] will be negative enough to make x[1]=0, the beginning of
512 | //the segment we're actually interested in here
513 | x[0] = -iter->get_duration();
514 | y[0] = iter->get_amplitude();
515 | for(int i = 1; i < 4; i++) {
516 | x[i] = x[i-1] + iter->get_duration();
517 | ++iter;
518 | y[i] = iter->get_amplitude();
519 | }
520 | //iter is now pointing at the 4th point of this set
521 |
522 | get_cspline_coefs(x,y,coefs);
523 |
524 | unsigned int i = 0;
525 | for(i = 0; i < bufsize && iter != breakpoint_list.end(); i++) {
526 | dest[i] = cspline_interp(coefs,x_in);
527 | ++x_in;
528 | //if we're past the end of the segment
529 | if(x_in > x[2]) {
530 | x_in -= x[2];
531 | for(int j = 0; j < 3; ++j) {
532 | x[j] = x[j+1] - x[2];
533 | y[j] = y[j+1];
534 | }
535 | x[3] = x[2] + iter->get_duration();
536 | if(++iter != breakpoint_list.end()) {
537 | y[3] = iter->get_amplitude();
538 | get_cspline_coefs(x,y,coefs);
539 | }
540 | }
541 | }
542 | return i;
543 | }
544 | }
545 |
--------------------------------------------------------------------------------
/src/gendy_waveform.h:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #ifndef GENDY_WAVEFORM_H
31 | #define GENDY_WAVEFORM_H
32 |
33 | #include "types.h"
34 | #include "breakpoint.h"
35 | #include
36 |
37 | class gendy_waveform
38 | {
39 | // keep track of where we are in the current segment(in samples)
40 | gendydur_t phase;
41 | // average wavelength in samples.
42 | float average_wavelength;
43 | // list of breakpoints plus guard points(for continuity)
44 | std::list breakpoint_list;
45 | // the first breakpoint after the guard points
46 | std::list::iterator breakpoint_begin;
47 | // the first guard point after the breakpoints
48 | std::list::iterator breakpoint_end;
49 | // the current breakpoint that the next request block will start with
50 | std::list::iterator breakpoint_current;;
51 | // set the type of interpolation(see defines at top)
52 | interpolation_t interpolation_type;
53 | // the waveshape that the breakpoints will gravitate to
54 | waveshape_t waveshape;
55 | // constrain endpoints to 0
56 | bool constrain_endpoints;
57 | // determines the motion of the breakpoints. expected to be 0-1, where
58 | // 0 is no motion and 1 is basically fully random jumps
59 | float step_width;
60 | float step_height;
61 | // the extent to which the duration and amplitude are pulled to match
62 | // the waveshape. ranges from 0 to 1
63 | float duration_pull;
64 | float amplitude_pull;
65 | // eventually debugging info will be switchable on an object-basis
66 | bool debug;
67 |
68 | void move_breakpoints();
69 | void generate_from_breakpoints();
70 | void add_breakpoint();
71 | void remove_breakpoint();
72 | void center_breakpoints();
73 | void reset_breakpoints();
74 | void set_pre_guardpoints(unsigned int guardpoints);
75 | void set_post_guardpoints(unsigned int guardpoints);
76 |
77 | public:
78 | gendy_waveform();
79 | ~gendy_waveform();
80 | //gendy_waveform(float freq);
81 | void set_num_breakpoints(int new_size);
82 | void set_avg_wavelength(float new_wavelength);
83 | void set_interpolation(interpolation_t new_interpolation);
84 | void set_waveshape(waveshape_t new_waveshape);
85 | void set_step_width(float new_width);
86 | void set_step_height(float new_height);
87 | void set_amplitude_pull(float new_pull);
88 | void set_duration_pull(float new_pull);
89 | void set_constrain_endpoints(bool constrain);
90 | float get_wavelength() const;
91 | unsigned int get_num_breakpoints() const;
92 | unsigned int get_num_guardpoints() const;
93 | unsigned int get_block(gendysamp_t *dest, unsigned int bufsize);
94 | unsigned int get_cycle(gendysamp_t *dest, unsigned int bufsize) const;
95 | }; //end gendy_waveform class def
96 |
97 | #endif /* GENDY_WAVEFORM_H */
98 |
--------------------------------------------------------------------------------
/src/gendy~.cpp:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | // gendy~ - an implementation of Iannis Xenakis' Dynamic
31 | // Stochastic Synthesis as an object for Pure Data.
32 | //
33 | // This project uses Thomas Grill's Flext framework, which
34 | // is necessary to compile and run it.
35 | //
36 |
37 | #include
38 | #include
39 | #include "gendy~.h"
40 | #include "log.h"
41 |
42 | using namespace std;
43 |
44 | #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 502)
45 | #error You need at least flext version 0.5.2
46 | #endif
47 |
48 |
49 | // object class constructor(run at each gendy object creation)
50 | gendy::gendy() {
51 | id = gendy_count;
52 | gendy_count++;
53 | if(debug)
54 | print_log("gendy~ #%d: Constructor initiated", id, LOG_DEBUG);
55 | AddInAnything("control input"); // control input
56 | AddOutSignal("audio out"); // audio output
57 |
58 | display_buf = NULL;
59 |
60 | if(debug)
61 | print_log("gendy~ #%d: Constructor terminated", id, LOG_DEBUG);
62 | }
63 |
64 | gendy::~gendy() {
65 | if(debug)
66 | print_log("gendy~ #%d: Destructor initiated", id, LOG_DEBUG);
67 | gendy_count--;
68 | if(debug)
69 | print_log("gendy~ #%d: Destructor terminated", id, LOG_DEBUG);
70 | }
71 |
72 | void gendy::class_setup(t_classid thisclass) {
73 | // associate methods with incoming messages on inlet 0
74 | print_log("Class constructor beginning", LOG_DEBUG);
75 | FLEXT_CADDMETHOD_(thisclass, 0, "freq", set_frequency);
76 | FLEXT_CADDMETHOD_(thisclass, 0, "breakpoints", set_num_breakpoints);
77 | FLEXT_CADDMETHOD_(thisclass, 0, "h_step", set_h_step);
78 | FLEXT_CADDMETHOD_(thisclass, 0, "v_step", set_v_step);
79 | FLEXT_CADDMETHOD_(thisclass, 0, "h_pull", set_h_pull);
80 | FLEXT_CADDMETHOD_(thisclass, 0, "v_pull", set_v_pull);
81 | FLEXT_CADDMETHOD_(thisclass, 0, "linear", set_interpolation_lin);
82 | FLEXT_CADDMETHOD_(thisclass, 0, "cubic", set_interpolation_cubic);
83 | FLEXT_CADDMETHOD_(thisclass, 0, "spline", set_interpolation_spline);
84 | FLEXT_CADDMETHOD_(thisclass, 0, "sinc", set_interpolation_sinc);
85 | FLEXT_CADDMETHOD_(thisclass, 0, "flat", set_waveform_flat);
86 | FLEXT_CADDMETHOD_(thisclass, 0, "sine", set_waveform_sine);
87 | FLEXT_CADDMETHOD_(thisclass, 0, "square", set_waveform_square);
88 | FLEXT_CADDMETHOD_(thisclass, 0, "debug", set_debug);
89 | FLEXT_CADDMETHOD_(thisclass, 0, "table", set_outbuf);
90 | FLEXT_CADDMETHOD_(thisclass, 0, "redraw", redraw);
91 | print_log("",LOG_INFO);
92 | print_log("-- gendy~ v%d.%d.%d by Spencer Russell --",
93 | GENDY_MAJ, GENDY_MIN, GENDY_REV, LOG_INFO);
94 | print_log("gendy~: please report bugs to https://github.com/ssfrr/gendyflext/issues", LOG_INFO);
95 | print_log("Class constructor ending", LOG_DEBUG);
96 | }
97 |
98 | // Now we define our DSP function. It gets these arguments:
99 | //
100 | // n: length of signal vector.
101 | // float *const *in, float *const *out:
102 | // These are arrays of signal vectors(in is a pointer to const pointer to float)
103 |
104 | void gendy::m_signal(int n, float *const *in, float *const *out) {
105 | waveform.get_block(out[0], n);
106 | }
107 |
108 | // Message handling functions
109 |
110 | void gendy::set_frequency(float new_freq) {
111 | print_log("set_frequency(%f)", new_freq, LOG_DEBUG);
112 | waveform.set_avg_wavelength(Samplerate() / new_freq);
113 | }
114 |
115 | void gendy::set_num_breakpoints(float num_breakpoints) {
116 | print_log("set_num_breakpoints(%f)", num_breakpoints, LOG_DEBUG);
117 | waveform.set_num_breakpoints(num_breakpoints);
118 | }
119 |
120 | void gendy::set_h_step(float new_stepsize) {
121 | print_log("set_h_step(%f)", new_stepsize, LOG_DEBUG);
122 | waveform.set_step_width(new_stepsize);
123 | }
124 |
125 | void gendy::set_v_step(float new_stepsize) {
126 | print_log("set_v_step(%f)", new_stepsize, LOG_DEBUG);
127 | waveform.set_step_height(new_stepsize);
128 | }
129 |
130 | void gendy::set_h_pull(float new_pull) {
131 | print_log("set_h_pull(%f)", new_pull, LOG_DEBUG);
132 | waveform.set_duration_pull(new_pull);
133 | }
134 |
135 | void gendy::set_v_pull(float new_pull) {
136 | print_log("set_v_pull(%f)", new_pull, LOG_DEBUG);
137 | waveform.set_amplitude_pull(new_pull);
138 | }
139 |
140 | void gendy::set_interpolation_lin() {
141 | print_log("set_interpolation_lin()", LOG_DEBUG);
142 | set_interpolation(LINEAR);
143 | }
144 |
145 | void gendy::set_interpolation_cubic() {
146 | print_log("set_interpolation_cubic()", LOG_DEBUG);
147 | set_interpolation(CUBIC);
148 | }
149 |
150 | void gendy::set_interpolation_spline() {
151 | print_log("set_interpolation_spline()", LOG_DEBUG);
152 | set_interpolation(SPLINE);
153 | }
154 |
155 | void gendy::set_interpolation_sinc() {
156 | print_log("set_interpolation_sinc()", LOG_DEBUG);
157 | set_interpolation(SINC);
158 | }
159 |
160 | void gendy::set_waveform_flat() {
161 | print_log("set_waveform_flat()", LOG_DEBUG);
162 | set_waveform(FLAT);
163 | }
164 |
165 | void gendy::set_waveform_sine() {
166 | print_log("set_waveform_sine()", LOG_DEBUG);
167 | set_waveform(SINE);
168 | }
169 |
170 | void gendy::set_waveform_square() {
171 | print_log("set_waveform_square()", LOG_DEBUG);
172 | set_waveform(SQUARE);
173 | }
174 |
175 | void gendy::set_debug(int new_debug) {
176 | print_log("set_debug(%d)", new_debug, LOG_DEBUG);
177 | if(new_debug)
178 | debug = true;
179 | else
180 | debug = false;
181 | }
182 |
183 | // TODO let flext take care of buffer setting argument checking?
184 |
185 | void gendy::set_outbuf(short argc, t_atom *argv) {
186 | if(argc == 0)
187 | // no argument toggles waveform display
188 | print_log("gendy~: missing buffer name", LOG_ERROR);
189 | else if(argc == 1) {
190 | if(IsFloat(argv[0]))
191 | print_log("gendy~: invalid buffer name", LOG_ERROR);
192 | else if(IsSymbol(argv[0])) {
193 | // symbol argument, set output buffer
194 | // TODO: better error reporting
195 | // delete existing buffer reference
196 | if(display_buf) {
197 | delete display_buf;
198 | }
199 | display_buf = new buffer(GetSymbol(argv[0]));
200 | if(!display_buf->Ok()) {
201 | print_log("gendy~: buffer not valid", LOG_ERROR);
202 | delete display_buf;
203 | display_buf = NULL;
204 | }
205 | }
206 | }
207 | }
208 |
209 | // private class methods
210 | void gendy::set_interpolation(interpolation_t new_interpolation) {
211 | waveform.set_interpolation(new_interpolation);
212 | }
213 |
214 | void gendy::set_waveform(waveshape_t new_waveform) {
215 | waveform.set_waveshape(new_waveform);
216 | }
217 |
218 | void gendy::redraw() {
219 | int n = 0;
220 | gendysamp_t *temp_buf;
221 |
222 | if(!display_buf || !display_buf->Ok()) {
223 | print_log("gendy~: Invalid Buffer", LOG_ERROR);
224 | return;
225 | }
226 |
227 | //TODO: is there a way to do this without the temp buffer?
228 | flext::buffer::lock_t state = display_buf->Lock();
229 | display_buf->Update();
230 | // resize table to fit 1 wavelength
231 | //display_buf->Frames(current_wavelength, false, false);
232 | int bufsize = display_buf->Frames();
233 | temp_buf = new gendysamp_t[bufsize];
234 | //TODO: this is not threadsafe. wavelength could change.
235 | int wavelength = waveform.get_wavelength();
236 | waveform.get_cycle(temp_buf, bufsize);
237 | // here we copy from the raw float array to the flext buffer object
238 | for(; n < wavelength && n < bufsize; ++n)
239 | (*display_buf)[n] = temp_buf[n];
240 | delete temp_buf;
241 | // zero out the rest of the buffer
242 | while(n < bufsize)
243 | (*display_buf)[n++]= 0;
244 | display_buf->Dirty(true);
245 | display_buf->Unlock(state);
246 | }
247 |
248 | //register the gendy class as a PD or Max object
249 | FLEXT_NEW_DSP("gendy~", gendy)
250 |
--------------------------------------------------------------------------------
/src/gendy~.h:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | // gendy~ - an implementation of Iannis Xenakis' Dynamic
31 | // Stochastic Synthesis as an object for Pure Data.
32 | //
33 | // This project uses Thomas Grill's Flext framework, which
34 | // is necessary to compile and run it.
35 |
36 | #ifndef GENDY_H
37 | #define GENDY_H
38 | #include "gendy_waveform.h"
39 | //
40 | // gendy~ version 0.6.0:
41 | const int GENDY_MAJ = 0;
42 | const int GENDY_MIN = 6;
43 | const int GENDY_REV = 0;
44 |
45 | // A flext dsp external ("tilde object") inherits from the class flext_dsp
46 | class gendy: public flext_dsp {
47 | // flext macro magic
48 | FLEXT_HEADER_S(gendy, flext_dsp, class_setup)
49 |
50 | public:
51 | gendy();
52 | ~gendy();
53 |
54 | protected:
55 | // here we declare the virtual DSP function
56 | virtual void m_signal(int n, float *const *in, float *const *out);
57 |
58 | // Message handling functions
59 | void set_frequency(float new_freq);
60 | void set_num_breakpoints(float num_breakpoints);
61 | void set_h_step(float new_stepsize);
62 | void set_v_step(float new_stepsize);
63 | void set_h_pull(float new_pull);
64 | void set_v_pull(float new_pull);
65 | void set_interpolation_lin();
66 | void set_interpolation_cubic();
67 | void set_interpolation_spline();
68 | void set_interpolation_sinc();
69 | void set_waveform_flat();
70 | void set_waveform_sine();
71 | void set_waveform_square();
72 | void set_debug(int new_debug);
73 | void set_outbuf(short argc, t_atom *argv);
74 | void redraw();
75 |
76 | private:
77 | gendy_waveform waveform;
78 | static bool debug;
79 | // class-wide variable to keep track of how many objects exist
80 | static unsigned int gendy_count;
81 | // instance ID
82 | unsigned int id;
83 |
84 | // waveform display buffer variables
85 | // buffer to copy to for waveform display
86 | flext::buffer *display_buf;
87 |
88 | // Internal class methods
89 | static void class_setup(t_classid thisclass);
90 | void set_interpolation(interpolation_t interpolation);
91 | void set_waveform(waveshape_t waveform);
92 |
93 | // register the callbacks, and tell flext their calling format
94 | FLEXT_CALLBACK_F(set_frequency)
95 | FLEXT_CALLBACK_I(set_num_breakpoints)
96 | FLEXT_CALLBACK_F(set_h_step)
97 | FLEXT_CALLBACK_F(set_v_step)
98 | FLEXT_CALLBACK_F(set_h_pull)
99 | FLEXT_CALLBACK_F(set_v_pull)
100 | FLEXT_CALLBACK(set_interpolation_lin)
101 | FLEXT_CALLBACK(set_interpolation_cubic)
102 | FLEXT_CALLBACK(set_interpolation_spline)
103 | FLEXT_CALLBACK(set_interpolation_sinc)
104 | FLEXT_CALLBACK(set_waveform_flat)
105 | FLEXT_CALLBACK(set_waveform_sine)
106 | FLEXT_CALLBACK(set_waveform_square)
107 | FLEXT_CALLBACK_I(set_debug)
108 | FLEXT_CALLBACK_V(set_outbuf)
109 | FLEXT_CALLBACK(redraw)
110 | };
111 | unsigned int gendy::gendy_count = 0;
112 | bool gendy::debug = true;
113 | #endif /* GENDY_H */
114 |
--------------------------------------------------------------------------------
/src/log.cpp:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #include "log.h"
31 | #include
32 |
33 | // shows msg if allowed by LOG_LEVEL
34 | void print_log(const char *msg, int level){
35 | if (LOG_LEVEL >= level) {
36 | post(msg);
37 | }
38 | }
39 |
40 | void print_log(const char *msg, int arg1, int level){
41 | if (LOG_LEVEL >= level) {
42 | post(msg, arg1);
43 | }
44 | }
45 |
46 | void print_log(const char *msg, int arg1, int arg2, int arg3, int level) {
47 | if (LOG_LEVEL >= level) {
48 | post(msg, arg1, arg2, arg3);
49 | }
50 | }
51 |
52 | void print_log(const char *msg, unsigned int arg1, int level){
53 | if (LOG_LEVEL >= level) {
54 | post(msg, arg1);
55 | }
56 | }
57 |
58 | void print_log(const char *msg, float arg1, int level){
59 | if (LOG_LEVEL >= level) {
60 | post(msg, arg1);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/log.h:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #ifndef LOG_H
31 | #define LOG_H
32 |
33 | // define and set log levels
34 | #define LOG_NONE 0
35 | #define LOG_ERROR 1
36 | #define LOG_INFO 2
37 | #define LOG_DEBUG 3
38 |
39 | #define LOG_LEVEL LOG_INFO
40 |
41 | void print_log(const char *msg, int level);
42 | void print_log(const char *msg, int arg1, int level);
43 | void print_log(const char *msg, int arg1, int arg2, int arg3, int level);
44 | void print_log(const char *msg, unsigned int arg1, int level);
45 | void print_log(const char *msg, float arg1, int level);
46 |
47 | #endif /* LOG_H */
48 |
--------------------------------------------------------------------------------
/src/splines.cpp:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #include "splines.h"
31 |
32 | void get_cspline_coefs(double *xp, double *yp, double *coefs) {
33 | double h[3];
34 | // h[n] is the x-distance between x[n] and x[n+1]
35 | for(int i = 0; i < 3; i++)
36 | h[i] = xp[i+1] - xp[i];
37 | // d[i] is the slope of the line segment connecting point i
38 | // to point i+1
39 | double d[3];
40 | for(int i = 0; i < 3; i++)
41 | d[i] = (yp[i+1] - yp[i]) / h[i];
42 | //yd[n] is the derivitive of f(x) at xp[1] and xp[2]. It's a
43 | //weighted average of the two adjacent line segments
44 | double yd[3];
45 | for(int i = 1; i < 3; i++)
46 | yd[i] = (d[i] * h[i-1] + d[i-1] * h[i]) / (h[i-1] + h[i]);
47 | // Here we actually calculate the coefficients
48 | coefs[0] = (h[1]*(yd[2] - yd[1]) -
49 | 2 * (yp[2] - yp[1] - h[1] * yd[1])) / (h[1] * h[1] * h[1]);
50 | coefs[1] = (3 * (yp[2] - yp[1] - h[1] * yd[1]) -
51 | h[1] * (yd[2] - yd[1])) / (h[1] * h[1]);
52 | coefs[2] = yd[1];
53 | coefs[3] = yp[1];
54 | }
55 |
56 | double cspline_interp(double *coefs, double x) {
57 | return coefs[3] + x * (coefs[2] + x * (coefs[1] + coefs[0] * x));
58 | }
59 |
--------------------------------------------------------------------------------
/src/splines.h:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #ifndef SPLINES_H
31 | #define SPLINES_H
32 |
33 | void get_cspline_coefs(double *xp, double *yp, double *coefs);
34 | double cspline_interp(double *coefs, double x);
35 |
36 | #endif /* SPLINES_H */
37 |
--------------------------------------------------------------------------------
/src/types.h:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #ifndef TYPES_H
31 | #define TYPES_H
32 |
33 | // define interpolation types
34 | enum interpolation_t{ LINEAR, CUBIC, SPLINE, SINC };
35 |
36 | // define center waveform shapes
37 | enum waveshape_t { FLAT, SINE, SQUARE, TRIANGLE, SAWTOOTH };
38 |
39 | // define data types
40 | typedef float gendydur_t;
41 | typedef float gendyamp_t;
42 | typedef float gendysamp_t;
43 |
44 | #endif /* TYPES_H */
45 |
--------------------------------------------------------------------------------
/src/util.cpp:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #include "util.h"
31 | #include
32 | #include
33 |
34 | // return a uniformly distributed double-precision float between 0 and 1
35 | double randf() {
36 | return rand() / (double)RAND_MAX;
37 | }
38 |
39 | // returns gaussian random variable with mu 0 and sigma 1
40 | // From the GNU Scientific Library, src/randist/gauss.c
41 |
42 | double gauss() {
43 | double x, y, r2;
44 | do {
45 | /* choose x,y in uniform square (-1,-1) to (+1,+1) */
46 | x = -1 + 2 * randf();
47 | y = -1 + 2 * randf();
48 |
49 | /* see if it is in the unit circle */
50 | r2 = x * x + y * y;
51 | } while (r2 > 1.0 || r2 == 0);
52 |
53 | /* Box-Muller transform */
54 | return y * sqrt (-2.0 * log(r2) / r2);
55 | }
56 |
57 | int round(float num) {
58 | return int(floor(num + 0.5));
59 | }
60 |
--------------------------------------------------------------------------------
/src/util.h:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * libgendy
4 | *
5 | * a library implementing Iannis Xenakis's Dynamic Stochastic Synthesis
6 | *
7 | * Copyright 2009,2010 Spencer Russell
8 | * Released under the GPLv3
9 | *
10 | * This file is part of libgendy.
11 | *
12 | * libgendy is free software: you can redistribute it and/or
13 | * modify it under the terms of the GNU General Public License version 3 as
14 | * published by the Free Software Foundation.
15 | *
16 | * libgendy is distributed in the hope that it will be useful, but
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 | * more details.
20 | *
21 | * You should have received a copy of the GNU General Public License along with
22 | * libgendy. If not, see .
23 | *
24 | *
25 | ********************************************/
26 |
27 |
28 |
29 |
30 | #ifndef UTIL_H
31 | #define UTIL_H
32 |
33 | // misc utility functions
34 |
35 | // return a uniformly distributed double-precision float between 0 and 1
36 | double randf();
37 |
38 | // returns gaussian random variable with mu 0 and sigma 1
39 | // From the GNU Scientific Library, src/randist/gauss.c, released under GPL
40 | double gauss();
41 |
42 | // returns nearest integer. X.5 always rounded to X+1, so it's non-symmetrical
43 | int round(float num);
44 |
45 | #endif /* UTIL_H */
46 |
--------------------------------------------------------------------------------