-
Notifications
You must be signed in to change notification settings - Fork 0
/
Arpeggiator.sc
162 lines (160 loc) · 4.24 KB
/
Arpeggiator.sc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
Arpeggiator {
// TODO: også kunne sætte arr som Pseq eller Routine
// schedulering af ændringer -> sæt den her array af notes ved næste takts begyndelse
// have arr til at være en liste af en custom klasse hvor man både kan sætte tonehøjde og andre værdier der skal gives videre til synthen
var <>synth, <key, <arr, <dur = 0.3333333, dur_stream;
var <arr_size = 3, <arr_start = 30, <arr_step = 9;
var <>dur_ratio = 0.6, <amp = 0.2, amp_stream;
var <>routine, <initial_routine;
var <>array_transform_function;
var <>note_correct = nil;
var <>synth_args;
var <>break_loop = false;
var <>scheduler;
*new {arg synth_name, key;
^super.new.init(synth_name, key);
}
init {arg synth_name, key_name;
this.set_note_correct;
scheduler = TempoClock.default;
amp_stream = amp;
dur_stream = dur;
synth = synth_name;
synth_args = Dictionary.new;
if(key_name.isNil, {
key = (synth_name ++ Date.localtime).asSymbol;
}, {
key = key_name.asSymbol;
});
array_transform_function = {arg arr; arr};
arr = Array.series(arr_size, arr_start, arr_step);
routine = Tdef((key + "_arp").asSymbol, {
loop{
// se under Function for helpfile til block
block{arg break;
var transformed_arr = array_transform_function.value(arr);
transformed_arr.do({arg item;
var snth;
var dur_cur = dur_stream.next;
if(item.class != Symbol, {
note_correct !? item = note_correct.value(item) ?? item = item;
snth = Synth(synth, [\freq, item.midicps, \dur, dur_cur * dur_ratio, \amp, amp_stream.next] ++ synth_args.asKeyValuePairs);
// NodeWatcher gør at man kan bruge Node.isPlaying og Node.isRunning
NodeWatcher.register(snth, true);
});
dur_cur.wait;
if(snth.isNil.not.and(snth.isPlaying), {
snth.release;
});
if(break_loop == true, {
break_loop = false;
break.value;
});
});
//0.02.wait; // en kort wait sørger for at routinen ikke bliver overbelastet så den ikke svarer
}
}
});
initial_routine = routine;
}
arr_{arg new_arr;
arr = new_arr;
// nødvendigt for at kunne genstarte do-loops
// der fx kører på en uendelig Pseq
break_loop = true;
}
arr_size_{arg size;
arr = Array.series(size, arr_start, arr_step);
arr_size = size;
}
arr_start_{arg start;
arr = Array.series(arr_size, start, arr_step);
arr_start = start;
}
arr_step_{arg step;
arr = Array.series(arr_size, arr_start, step);
arr_step = step;
}
// convert to stream to allow calling next from playing routine
stream_factory {arg value;
if(value.isKindOf(Array),
{^Pseq(value, inf).asStream},
{^value.asStream}
);
}
amp_{arg new_amp;
amp_stream = this.stream_factory(new_amp);
amp = new_amp;
}
dur_{arg new_dur;
scheduler.play({
// hvorfor to forskellige variable her?
dur_stream = this.stream_factory(new_dur);
dur = new_dur;
routine.reset
}, scheduler.timeToNextBeat);
}
play {
routine.play;
}
stop {
routine.stop;
routine.reset;
}
pyramid {
array_transform_function = {arg arr; arr.pyramid};
}
mirror {
array_transform_function = {arg arr; arr.mirror};
}
set_note_correct {arg scale = #[0, 2, 4, 5, 7, 9, 11];
// finder den tone i skalaen, som er tættest på den givne tone
note_correct = {arg item;
if(item.class == Symbol, {item}, {
if(item.class == Array, {
item.collect({arg arr_item;
this.findMatchByScale(scale, arr_item);
});
}, {
this.findMatchByScale(scale, item)
});
});
}
}
findMatchByScale {arg scale, item;
var base = (item / 10).floor * 10;
var match = (item % (base + scale));
var close = scale[match.find((match.copy.sort)[0].asArray)];
^(base + close);
}
set_notes {arg notes;
// this ser ud til at være nødvendig her for at få ændringer til at slå igennem
this.arr = notes.collect({arg note;
note.tone;
});
this.dur = notes.collect({arg note;
note.dur;
});
this.amp = notes.collect({arg note;
if(note.amp.isNil.not, {
note.amp;
}, {amp});
});
}
clear_note_correct {
note_correct = nil;
}
}
ArpNote {
var <>tone, <>dur, <>amp;
*new{arg tone, dur, amp;
^super.new.init(tone, dur, amp);
}
init{arg toneArg, durArg, ampArg;
tone = toneArg;
dur = durArg;
amp = ampArg;
}
}
// alias for ArpNote
AN : ArpNote{}