xi-lang 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -15
- data/lib/xi/core_ext/integer.rb +11 -0
- data/lib/xi/core_ext/numeric.rb +2 -8
- data/lib/xi/core_ext/scalar.rb +1 -6
- data/lib/xi/core_ext.rb +1 -1
- data/lib/xi/osc/version.rb +5 -0
- data/lib/xi/osc.rb +36 -0
- data/lib/xi/pattern/generators.rb +7 -7
- data/lib/xi/pattern/transforms.rb +9 -9
- data/lib/xi/pattern.rb +4 -4
- data/lib/xi/supercollider/stream.rb +128 -0
- data/lib/xi/supercollider/version.rb +5 -0
- data/lib/xi/supercollider.rb +8 -0
- data/lib/xi/version.rb +1 -1
- data/synthdefs/other.scd +43 -0
- data/synthdefs/superdirt.scd +322 -0
- metadata +11 -5
- data/lib/xi/core_ext/fixnum.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2354b1293961d34731653d4461341638cc38e733a0c762b29ad8a7cc7574a7b
|
4
|
+
data.tar.gz: 3a3f2e8f0ce893304cde881800c03c33fe14e9ef01e76ba9810c1a2c3f9d8348
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b13a449ea692bfafc775fe0af0d05997655d15493e33bc2849d77e7237c58a4bdd5af89f9962c97eb265462fa353b5b468678cdf1ffe416e90b7c716b663151b
|
7
|
+
data.tar.gz: fdaaf2a270cf50cbe45de430b23269cd5e30d43ca145bd4d691a19801e3e355df1f3ba6c99f9b33d9eab3ec6e80ac257b3cb95e8c7fb066036ba0025d3ab1d02
|
data/README.md
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
# Xi [](https://travis-ci.org/xi-livecode/xi)
|
2
2
|
|
3
|
-
Xi
|
4
|
-
|
5
|
-
|
3
|
+
Xi is a musical pattern language inspired in Tidal and SuperCollider for
|
4
|
+
building higher-level musical constructs easily. It is implemented on the Ruby
|
5
|
+
programming language and uses SuperCollider as a backend.
|
6
6
|
|
7
|
-
Xi is only a patterns library, but can talk to
|
8
|
-
|
9
|
-
|
10
|
-
- MIDI devices
|
7
|
+
Xi is only a patterns library, but can talk to
|
8
|
+
[SuperCollider](https://github.com/supercollider/supercollider) synths or MIDI
|
9
|
+
devices.
|
11
10
|
|
12
11
|
*NOTE*: Be advised that this project is in very early alpha stages. There are a
|
13
12
|
multiple known bugs, missing features, documentation and tests.
|
@@ -40,17 +39,20 @@ clap.set n: s("..x. xyz. .x.. .xyx", 60, 61, 60).p.decelerate(2),
|
|
40
39
|
|
41
40
|
### Quickstart
|
42
41
|
|
43
|
-
You will need Ruby 2.
|
44
|
-
|
45
|
-
|
42
|
+
You will need Ruby 2.4+ installed on your system. Check by running `ruby -v`.
|
43
|
+
To install Xi you must install the core libraries and REPL, and then one or
|
44
|
+
more backends.
|
45
|
+
|
46
|
+
$ gem install xi-lang
|
46
47
|
|
47
|
-
|
48
|
+
Available backends:
|
48
49
|
|
49
|
-
|
50
|
+
* xi-midi: MIDI devices support
|
51
|
+
* xi-superdirt: [SuperDirt](https://github.com/musikinformatik/SuperDirt) backend
|
50
52
|
|
51
|
-
|
53
|
+
For example:
|
52
54
|
|
53
|
-
$ gem install xi-lang xi-
|
55
|
+
$ gem install xi-lang xi-superdirt
|
54
56
|
|
55
57
|
Then run Xi REPL with:
|
56
58
|
|
@@ -100,4 +102,4 @@ the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
100
102
|
|
101
103
|
## License
|
102
104
|
|
103
|
-
See [LICENSE](LICENSE)
|
105
|
+
See [LICENSE](LICENSE.txt)
|
data/lib/xi/core_ext/numeric.rb
CHANGED
@@ -21,14 +21,8 @@ module Xi::CoreExt
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
include Xi::CoreExt::Numeric
|
27
|
-
end
|
28
|
-
else
|
29
|
-
class Integer
|
30
|
-
include Xi::CoreExt::Numeric
|
31
|
-
end
|
24
|
+
class Integer
|
25
|
+
include Xi::CoreExt::Numeric
|
32
26
|
end
|
33
27
|
|
34
28
|
class Float
|
data/lib/xi/core_ext/scalar.rb
CHANGED
@@ -8,12 +8,7 @@ module Xi::CoreExt
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
class Fixnum; include Xi::CoreExt::Scalar; end
|
13
|
-
else
|
14
|
-
class Integer; include Xi::CoreExt::Scalar; end
|
15
|
-
end
|
16
|
-
|
11
|
+
class Integer; include Xi::CoreExt::Scalar; end
|
17
12
|
class Float; include Xi::CoreExt::Scalar; end
|
18
13
|
class String; include Xi::CoreExt::Scalar; end
|
19
14
|
class Symbol; include Xi::CoreExt::Scalar; end
|
data/lib/xi/core_ext.rb
CHANGED
data/lib/xi/osc.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "xi/osc/version"
|
2
|
+
require 'osc-ruby'
|
3
|
+
|
4
|
+
module Xi
|
5
|
+
module OSC
|
6
|
+
def initialize(name, clock, server: 'localhost', port:, **opts)
|
7
|
+
super
|
8
|
+
@osc = ::OSC::Client.new(server, port)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def send_msg(address, *args)
|
14
|
+
msg = message(address, *args)
|
15
|
+
debug(__method__, msg.address, *msg.to_a)
|
16
|
+
send_osc_msg(msg)
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_bundle(address, *args, at: Time.now)
|
20
|
+
msg = message(address, *args)
|
21
|
+
bundle = ::OSC::Bundle.new(at, msg)
|
22
|
+
debug(__method__, msg.address, at.to_i, at.usec, *msg.to_a)
|
23
|
+
send_osc_msg(bundle)
|
24
|
+
end
|
25
|
+
|
26
|
+
def message(address, *args)
|
27
|
+
::OSC::Message.new(address, *args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def send_osc_msg(msg)
|
31
|
+
@osc.send(msg)
|
32
|
+
rescue StandardError => err
|
33
|
+
error(err)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -61,7 +61,7 @@ module Xi
|
|
61
61
|
# peek P.rand([1, 2, 3, 4], 6) #=> [1, 3, 2, 2, 4, 3]
|
62
62
|
#
|
63
63
|
# @param list [#each] list of values
|
64
|
-
# @param repeats [
|
64
|
+
# @param repeats [Integer, Symbol] number or inf (default: 1)
|
65
65
|
# @return [Pattern]
|
66
66
|
#
|
67
67
|
def rand(list, repeats=1)
|
@@ -83,7 +83,7 @@ module Xi
|
|
83
83
|
# peek P.xrand([1, 2, 3], 8) #=> [1, 3, 2, 3, 1, 2, 3, 2]
|
84
84
|
#
|
85
85
|
# @param list [#each] list of values
|
86
|
-
# @param repeats [
|
86
|
+
# @param repeats [Integer, Symbol] number or inf (default: 1)
|
87
87
|
# @return [Pattern]
|
88
88
|
#
|
89
89
|
def xrand(list, repeats=1)
|
@@ -109,7 +109,7 @@ module Xi
|
|
109
109
|
# peek P.shuf([1, 2, 3], 3) #=> [2, 3, 1, 2, 3, 1, 2, 3, 1]
|
110
110
|
#
|
111
111
|
# @param list [#each] list of values
|
112
|
-
# @param repeats [
|
112
|
+
# @param repeats [Integer, Symbol] number or inf (default: 1)
|
113
113
|
# @return [Pattern]
|
114
114
|
#
|
115
115
|
def shuf(list, repeats=1)
|
@@ -137,8 +137,8 @@ module Xi
|
|
137
137
|
# P.sin(22).duration #=> (1/1)
|
138
138
|
# P.sin(19, 2).duration #=> (2/1)
|
139
139
|
#
|
140
|
-
# @param quant [
|
141
|
-
# @param delta [
|
140
|
+
# @param quant [Integer]
|
141
|
+
# @param delta [Integer] (default: 1)
|
142
142
|
# @return [Pattern]
|
143
143
|
#
|
144
144
|
def sin(quant, delta=1)
|
@@ -160,8 +160,8 @@ module Xi
|
|
160
160
|
# peek P.sin1(8).map { |i| i.round(2) }
|
161
161
|
# #=> [0.5, 0.85, 1.0, 0.85, 0.5, 0.15, 0.0, 0.15]
|
162
162
|
#
|
163
|
-
# @param quant [
|
164
|
-
# @param delta [
|
163
|
+
# @param quant [Integer]
|
164
|
+
# @param delta [Integer] (default: 1)
|
165
165
|
# @return [Pattern]
|
166
166
|
#
|
167
167
|
def sin1(quant, delta=1)
|
@@ -132,17 +132,17 @@ module Xi
|
|
132
132
|
# peek [1, 2, 3].p.seq(1, 1) #=> [2, 3, 1]
|
133
133
|
# peek [1, 2, 3].p.seq(2, 2) #=> [3, 2, 1, 3, 2, 1]
|
134
134
|
#
|
135
|
-
# @param repeats [
|
136
|
-
# @param offset [
|
135
|
+
# @param repeats [Integer] number (defaut: 1)
|
136
|
+
# @param offset [Integer] (default: 0)
|
137
137
|
# @return [Pattern]
|
138
138
|
#
|
139
139
|
def seq(repeats=1, offset=0)
|
140
|
-
unless repeats.is_a?(
|
141
|
-
fail ArgumentError, "repeats must be a non-negative
|
140
|
+
unless repeats.is_a?(Integer) && repeats >= 0
|
141
|
+
fail ArgumentError, "repeats must be a non-negative Integer"
|
142
142
|
end
|
143
143
|
|
144
|
-
unless offset.is_a?(
|
145
|
-
fail ArgumentError, "offset must be a non-negative
|
144
|
+
unless offset.is_a?(Integer) && offset >= 0
|
145
|
+
fail ArgumentError, "offset must be a non-negative Integer"
|
146
146
|
end
|
147
147
|
|
148
148
|
Pattern.new(self, size: size * repeats) do |y|
|
@@ -362,7 +362,7 @@ module Xi
|
|
362
362
|
# peek [1, 2, 3].p.rand #=> [2]
|
363
363
|
# peek [1, 2, 3, 4].p.rand(6) #=> [1, 3, 2, 2, 4, 3]
|
364
364
|
#
|
365
|
-
# @param repeats [
|
365
|
+
# @param repeats [Integer, Symbol] number or inf (default: 1)
|
366
366
|
# @return [Pattern]
|
367
367
|
#
|
368
368
|
def rand(repeats=1)
|
@@ -378,7 +378,7 @@ module Xi
|
|
378
378
|
# peek [1, 2, 3, 4, 5].p.xrand #=> [4]
|
379
379
|
# peek [1, 2, 3].p.xrand(8) #=> [1, 3, 2, 3, 1, 2, 3, 2]
|
380
380
|
#
|
381
|
-
# @param repeats [
|
381
|
+
# @param repeats [Integer, Symbol] number or inf (default: 1)
|
382
382
|
# @return [Pattern]
|
383
383
|
#
|
384
384
|
def xrand(repeats=1)
|
@@ -394,7 +394,7 @@ module Xi
|
|
394
394
|
# peek [1, 2, 3, 4, 5].p.xrand #=> [4]
|
395
395
|
# peek [1, 2, 3].p.xrand(8) #=> [1, 3, 2, 3, 1, 2, 3, 2]
|
396
396
|
#
|
397
|
-
# @param repeats [
|
397
|
+
# @param repeats [Integer, Symbol] number or inf (default: 1)
|
398
398
|
# @return [Pattern]
|
399
399
|
#
|
400
400
|
def shuf(repeats=1)
|
data/lib/xi/pattern.rb
CHANGED
@@ -59,7 +59,7 @@ module Xi
|
|
59
59
|
# # [3, 4, 1, 0]]
|
60
60
|
#
|
61
61
|
# @param source [Array]
|
62
|
-
# @param size [
|
62
|
+
# @param size [Integer] number of events per iteration
|
63
63
|
# @param delta [Numeric, Array<Numeric>, Pattern<Numeric>] event delta
|
64
64
|
# @param metadata [Hash]
|
65
65
|
# @yield [yielder, delta] yielder and event delta
|
@@ -345,7 +345,7 @@ module Xi
|
|
345
345
|
|
346
346
|
# Returns the first +n+ events from the pattern, starting from +cycle+
|
347
347
|
#
|
348
|
-
# @param n [
|
348
|
+
# @param n [Integer]
|
349
349
|
# @param cycle [Numeric]
|
350
350
|
# @return [Array] values
|
351
351
|
#
|
@@ -380,7 +380,7 @@ module Xi
|
|
380
380
|
#
|
381
381
|
# @see #take
|
382
382
|
#
|
383
|
-
# @param n [
|
383
|
+
# @param n [Integer]
|
384
384
|
# @param args same arguments as {#take}
|
385
385
|
# @return [Object, Array]
|
386
386
|
#
|
@@ -420,7 +420,7 @@ module Xi
|
|
420
420
|
# pattern size is assumed to be 1, so iteration size depends on delta
|
421
421
|
# values.
|
422
422
|
#
|
423
|
-
# @return [
|
423
|
+
# @return [Integer]
|
424
424
|
#
|
425
425
|
def iteration_size
|
426
426
|
finite? ? delta_size.lcm(@size) : delta_size
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'xi/stream'
|
2
|
+
require 'xi/osc'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Xi::Supercollider
|
6
|
+
class Stream < Xi::Stream
|
7
|
+
include Xi::OSC
|
8
|
+
|
9
|
+
MAX_NODE_ID = 10000
|
10
|
+
DEFAULT_PARAMS = {
|
11
|
+
out: 0,
|
12
|
+
amp: 1.0,
|
13
|
+
pan: 0.0,
|
14
|
+
vel: 127,
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(name, clock, server: 'localhost', port: 57110, base_node_id: 2000, **opts)
|
18
|
+
super
|
19
|
+
|
20
|
+
@base_node_id = base_node_id
|
21
|
+
@playing_synths = [].to_set
|
22
|
+
at_exit { free_playing_synths }
|
23
|
+
end
|
24
|
+
|
25
|
+
def set(params)
|
26
|
+
super(gate: params[:gate] || :freq, **params)
|
27
|
+
end
|
28
|
+
|
29
|
+
def stop
|
30
|
+
@mutex.synchronize do
|
31
|
+
@playing_synths.each do |so_id|
|
32
|
+
n_set(node_id(so_id), gate: 0)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def free_playing_synths
|
39
|
+
n_free(*@playing_synths.map { |so_id| node_id(so_id) })
|
40
|
+
end
|
41
|
+
|
42
|
+
def node_id(so_id)
|
43
|
+
(@base_node_id + so_id) % MAX_NODE_ID
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def transform_state
|
49
|
+
super
|
50
|
+
|
51
|
+
@state = DEFAULT_PARAMS.merge(@state)
|
52
|
+
|
53
|
+
if changed_param?(:db) && !changed_param?(:amp)
|
54
|
+
@state[:amp] = @state[:db].db_to_amp
|
55
|
+
@changed_params << :amp
|
56
|
+
end
|
57
|
+
|
58
|
+
if changed_param?(:midinote) && !changed_param?(:freq)
|
59
|
+
@state[:freq] = Array(@state[:midinote]).map(&:midi_to_cps)
|
60
|
+
@changed_params << :freq
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def do_gate_on_change(changes)
|
65
|
+
debug "Gate on change: #{changes}"
|
66
|
+
|
67
|
+
name = @state[:s] || :default
|
68
|
+
state_params = @state.reject { |k, _| %i(s).include?(k) }
|
69
|
+
|
70
|
+
freq = Array(state_params[:freq])
|
71
|
+
|
72
|
+
changes.each do |change|
|
73
|
+
at = Time.at(change.fetch(:at))
|
74
|
+
|
75
|
+
change.fetch(:so_ids).each.with_index do |so_id, i|
|
76
|
+
freq_i = freq.size > 0 ? freq[i % freq.size] : nil
|
77
|
+
|
78
|
+
s_new(name, node_id(so_id), **state_params, freq: freq_i, at: at)
|
79
|
+
@playing_synths << so_id
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def do_gate_off_change(changes)
|
85
|
+
debug "Gate off change: #{changes}"
|
86
|
+
|
87
|
+
changes.each do |change|
|
88
|
+
at = Time.at(change.fetch(:at))
|
89
|
+
|
90
|
+
change.fetch(:so_ids).each do |so_id|
|
91
|
+
n_set(node_id(so_id), gate: 0, at: at)
|
92
|
+
@playing_synths.delete(so_id)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def do_state_change
|
98
|
+
debug "State change: #{changed_state}"
|
99
|
+
@playing_synths.each do |so_id|
|
100
|
+
n_set(node_id(so_id), **changed_state)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def n_set(id, at: Time.now, **args)
|
105
|
+
send_bundle('/n_set', id, *osc_args(args), at: at)
|
106
|
+
end
|
107
|
+
|
108
|
+
def s_new(name, id, add_action: 0, target_id: 1, at: Time.now, **args)
|
109
|
+
send_bundle('/s_new', name.to_s, id.to_i, add_action.to_i,
|
110
|
+
target_id.to_i, *osc_args(args), at: at)
|
111
|
+
end
|
112
|
+
|
113
|
+
def n_free(*ids, at: Time.now)
|
114
|
+
send_bundle('/n_free', *ids, at: at)
|
115
|
+
end
|
116
|
+
|
117
|
+
def osc_args(**args)
|
118
|
+
args.map { |k, v| [k.to_s, coerce_osc_value(v)] }.flatten(1)
|
119
|
+
end
|
120
|
+
|
121
|
+
def coerce_osc_value(value)
|
122
|
+
v = Array(value).first
|
123
|
+
v = v.to_f if v.is_a?(Rational)
|
124
|
+
v = v.to_i if !v.is_a?(Float) && !v.is_a?(String) && !v.is_a?(Symbol)
|
125
|
+
v
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/xi/version.rb
CHANGED
data/synthdefs/other.scd
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
(
|
2
|
+
SynthDef(\kick, { |out=0, amp=1, freq=70, attack=0.001, xstart=1, xend=0.25, xdur=0.05, release=0.15, pan=0.5|
|
3
|
+
var sig = SinOsc.ar(freq * XLine.ar(xstart, xend, xdur));
|
4
|
+
var env = EnvGen.ar(Env.perc(attack, release, 1, -4), doneAction: 2);
|
5
|
+
sig = Pan2.ar(sig, pan) * env;
|
6
|
+
sig = (sig * 5).tanh;
|
7
|
+
OffsetOut.ar(out, Pan2.ar(sig * env, pan, amp * 0.25));
|
8
|
+
}).add;
|
9
|
+
|
10
|
+
SynthDef(\snare, { |out=0, amp=1, freq=1000, freq2=180, attack=0.01, release=0.2, pan=0|
|
11
|
+
var snd1 = WhiteNoise.ar(amp);
|
12
|
+
var snd2 = SinOsc.ar(freq2, 0, amp);
|
13
|
+
var env = Env.perc(attack, release).kr(doneAction: 2);
|
14
|
+
var sum = RHPF.ar(snd1 * env, 2500) + LPF.ar(snd2 * env, 1500);
|
15
|
+
OffsetOut.ar(out, Pan2.ar(sum, pan, amp * 0.1))
|
16
|
+
}).add;
|
17
|
+
|
18
|
+
SynthDef(\bassy, { |out=0, amp=1, freq=440, hctf=1000, lctf=5000, rq=0.5, attack=0.001, release=1, mul=1, pan=0.5|
|
19
|
+
var sig = Saw.ar(freq);
|
20
|
+
var env = EnvGen.ar(Env.perc(attack, release), doneAction: 2);
|
21
|
+
sig = mul * BHiPass.ar(RLPF.ar(sig, lctf * env, rq), hctf, rq);
|
22
|
+
OffsetOut.ar(out, Pan2.ar(sig * env, pan, amp * 0.1))
|
23
|
+
}).add;
|
24
|
+
|
25
|
+
SynthDef(\sin, { |out, amp=1, attack=0.001, release=1, sustain=1, pan=0, accelerate=0, freq=440, detune=0.1|
|
26
|
+
var env = EnvGen.ar(Env.perc(attack, release, 1, -4), timeScale: sustain / 2, doneAction: 2);
|
27
|
+
var sound = SinOsc.ar([freq, freq+detune] * Line.kr(1,1+accelerate, sustain));
|
28
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp));
|
29
|
+
}).add;
|
30
|
+
|
31
|
+
SynthDef(\fm, { |out, amp=1, attack=0.001, sustain=1, pan=0, accelerate=0, freq=440, carPartial=1, modPartial=1, index=3, mul=0.1, detune=0.1|
|
32
|
+
var env = EnvGen.ar(Env.perc(attack, 0.999, 1, -3), timeScale: sustain / 2, doneAction: 2);
|
33
|
+
var mod = SinOsc.ar(freq * modPartial * Line.kr(1,1+accelerate, sustain), 0, freq * index * LFNoise1.kr(5.reciprocal).abs);
|
34
|
+
var car = SinOsc.ar(([freq, freq+detune] * carPartial) + mod, 0, mul);
|
35
|
+
OffsetOut.ar(out, Pan2.ar(car * env, pan, amp));
|
36
|
+
}).add;
|
37
|
+
|
38
|
+
SynthDef(\saw, {|out, amp=1, attack=0.001, sustain=1, pan=0, accelerate=0, freq=440, detune=0.1|
|
39
|
+
var env = EnvGen.ar(Env.perc(attack, 0.999, 1, -4), timeScale: sustain / 2, doneAction: 2);
|
40
|
+
var sound = Saw.ar([freq, freq + detune] * Line.kr(1, 1 + accelerate, sustain));
|
41
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp * 0.1));
|
42
|
+
}).add;
|
43
|
+
)
|
@@ -0,0 +1,322 @@
|
|
1
|
+
//
|
2
|
+
// The following synth definitions were taken from Superdirt almost as is.
|
3
|
+
// Original file at https://github.com/musikinformatik/SuperDirt/blob/bb1536329896e6e211c3bafee7befb06d06fc856/library/default-synths-extra.scd
|
4
|
+
//
|
5
|
+
// Source code included in this file is licensed under GPL v2.
|
6
|
+
// Please refer to LICENSE file at
|
7
|
+
// https://github.com/musikinformatik/SuperDirt/blob/master/LICENSE
|
8
|
+
//
|
9
|
+
|
10
|
+
// Physical modeling of a vibrating string, using a delay line (CombL) excited
|
11
|
+
// by an intial pulse (Impulse). To make it a bit richer, I've combined two
|
12
|
+
// slightly detuned delay lines.
|
13
|
+
//
|
14
|
+
// "accelerate" is used for a pitch glide
|
15
|
+
// "sustain" changes the envelope timescale
|
16
|
+
(
|
17
|
+
SynthDef(\smandolin, { |out, amp=1, sustain=1, pan=0, accelerate=0, freq=440, detune=0.2|
|
18
|
+
var env = EnvGen.ar(Env.linen(0.002, 0.996, 0.002, 1,-3), timeScale: sustain, doneAction: 2);
|
19
|
+
var sound = Decay.ar(Impulse.ar(0,0,0.1), 0.1 * (freq.cpsmidi) / 69) * WhiteNoise.ar;
|
20
|
+
var pitch = freq * Line.kr(1, 1 + accelerate, sustain);
|
21
|
+
sound = CombL.ar(sound, 0.05, pitch.reciprocal * (1 - (detune/100)), sustain)
|
22
|
+
+ CombL.ar(sound, 0.05, pitch.reciprocal * (1 + (detune/100)), sustain);
|
23
|
+
OffsetOut.ar(out, Pan2.ar(sound * env * amp, pan))
|
24
|
+
}).add
|
25
|
+
);
|
26
|
+
|
27
|
+
// An example of additive synthesis, building up a gong-like noise from a sum
|
28
|
+
// of sine-wave harmonics. Notice how the envelope timescale and amplitude can
|
29
|
+
// be scaled as a function of the harmonic frequency.
|
30
|
+
// "voice" provides something like a tone knob
|
31
|
+
// "decay" adjusts how the harmonics decay as in the other SynthDefs
|
32
|
+
// "sustain" affects the overall envelope timescale
|
33
|
+
// "accelerate" for pitch glide
|
34
|
+
(
|
35
|
+
SynthDef(\sgong, { |out, amp=1, sustain=1, pan=0, accelerate=0, freq=440, voice=0, decay=1|
|
36
|
+
// lowest modes for clamped circular plate
|
37
|
+
var freqlist = [1.000, 2.081, 3.414, 3.893, 4.995, 5.954, 6.819, 8.280, 8.722, 8.882, 10.868, 11.180, 11.754, 13.710, 13.715, 15.057, 15.484, 16.469, 16.817, 18.628] ** 1.0;
|
38
|
+
var tscale = 100.0 / freq / (freqlist ** (2 - clip(decay, 0, 2)));
|
39
|
+
var ascale =freqlist ** clip(voice,0,4);
|
40
|
+
var sound = Mix.arFill(15, { arg i;
|
41
|
+
EnvGen.ar(Env.perc(0.01 * tscale[i], 0.5 * tscale[i], 0.2 * ascale[i]), timeScale: sustain * 5)
|
42
|
+
* SinOsc.ar(freq * freqlist[i] * Line.kr(1, 1 + accelerate, sustain))
|
43
|
+
});
|
44
|
+
OffsetOut.ar(out, Pan2.ar(sound * amp / 15, pan))
|
45
|
+
}).add
|
46
|
+
);
|
47
|
+
|
48
|
+
// Hooking into a nice synth piano already in Supercollider.
|
49
|
+
//
|
50
|
+
// Uses the "velocity" parameter to affect how hard the keys are pressed
|
51
|
+
// "sustain" controls envelope and decay time.
|
52
|
+
(
|
53
|
+
SynthDef(\spiano, { |out, amp=1, sustain=1, pan=0, velocity=1, detune=0.1, muffle=1, stereo=0.2, freq=440|
|
54
|
+
var env = EnvGen.ar(Env.linen(0.002, 0.996, 0.002, 1, -3), timeScale: sustain, doneAction: 2);
|
55
|
+
// the +0.01 to freq is because of edge case rounding internal to the MdaPiano synth
|
56
|
+
var sound = MdaPiano.ar(freq + 0.01, vel: velocity * 100, hard: 0.8 * velocity, decay: 0.1 * sustain,
|
57
|
+
tune: 0.5, random: 0.05, stretch: detune, muffle: 0.8 * muffle, stereo: stereo);
|
58
|
+
OffsetOut.ar(out, Pan2.ar(sound * env * amp * 0.35, pan))
|
59
|
+
}).add
|
60
|
+
);
|
61
|
+
|
62
|
+
// Waveguide mesh, hexagonal drum-like membrane
|
63
|
+
(
|
64
|
+
SynthDef(\shex, { |out, speed=1, sustain=1, pan=0, freq=440, accelerate=0|
|
65
|
+
var env = EnvGen.ar(Env.linen(0.02, 0.96, 0.02, 1,-3), timeScale: sustain, doneAction: 2);
|
66
|
+
var tension = 0.05 * freq / 400 * Line.kr(1, accelerate + 1, sustain);
|
67
|
+
var loss = 1.0 - (0.01 * speed / freq);
|
68
|
+
var sound = MembraneHexagon.ar(Decay.ar(Impulse.ar(0, 0, 1), 0.01), tension, loss);
|
69
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan))
|
70
|
+
}).add
|
71
|
+
);
|
72
|
+
|
73
|
+
// Kick Drum using Rumble-San's implementation as a starting point
|
74
|
+
// http://blog.rumblesan.com/post/53271713518/drum-sounds-in-supercollider-part-1
|
75
|
+
//
|
76
|
+
// "n" controls the kick frequency in a nonstandard way
|
77
|
+
// "sustain" affects overall envelope timescale
|
78
|
+
// "accelerate" sweeps the click filter freq
|
79
|
+
// "pitch1" affects the click frequency
|
80
|
+
// "decay" changes the click duration relative to the overall timescale
|
81
|
+
(
|
82
|
+
SynthDef(\skick, { |out, sustain=1, pan=0, accelerate=0, n=60, pitch1=1, decay=1, amp=1|
|
83
|
+
var env, sound, dur, clickdur;
|
84
|
+
env = EnvGen.ar(Env.linen(0.01, 0, 0.5, 1, -3), timeScale: sustain, doneAction: 2);
|
85
|
+
sound = SinOsc.ar((n - 25.5).midicps);
|
86
|
+
clickdur = 0.02 * sustain * decay;
|
87
|
+
sound = sound + (LPF.ar(WhiteNoise.ar(1), 1500 * pitch1 * Line.kr(1, 1 + accelerate, clickdur))
|
88
|
+
* Line.ar(1, 0, clickdur));
|
89
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp))
|
90
|
+
}).add
|
91
|
+
);
|
92
|
+
|
93
|
+
// A vaguely 808-ish kick drum
|
94
|
+
//
|
95
|
+
// "n" controls the chirp frequency
|
96
|
+
// "sustain" the overall timescale
|
97
|
+
// "speed" the filter sweep speed
|
98
|
+
// "voice" the sinewave feedback
|
99
|
+
(
|
100
|
+
SynthDef(\s808, { |out, speed=1, sustain=1, pan=0, voice=0, n=60, amp=1|
|
101
|
+
var env, sound, freq;
|
102
|
+
n = ((n>0)*n) + ((n<1)*3);
|
103
|
+
freq = (n*10).midicps;
|
104
|
+
env = EnvGen.ar(Env.linen(0.01, 0, 1, 1, -3), timeScale:sustain, doneAction:2);
|
105
|
+
sound = LPF.ar(SinOscFB.ar(XLine.ar(freq.expexp(10, 2000, 1000, 8000), freq, 0.025/speed), voice), 9000);
|
106
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp))
|
107
|
+
}).add
|
108
|
+
);
|
109
|
+
|
110
|
+
// Hi-hat using Rumble-San's implementation as a starting point
|
111
|
+
// http://blog.rumblesan.com/post/53271713518/drum-sounds-in-supercollider-part-1
|
112
|
+
//
|
113
|
+
// "n" using it in a weird way to provide some variation on the frequency
|
114
|
+
// "sustain" affects the overall envelope rate,
|
115
|
+
// "accelerate" sweeps the filter
|
116
|
+
(
|
117
|
+
SynthDef(\shat, {|out, sustain=1, pan=0, accelerate=0, n=60, amp=1, freq=2000|
|
118
|
+
var env, sound, accel, frq;
|
119
|
+
env = EnvGen.ar(Env.linen(0.01, 0, 0.3, 1, -3), timeScale: sustain, doneAction:2);
|
120
|
+
accel = Line.kr(1, 1+accelerate, 0.2*sustain);
|
121
|
+
frq = freq*accel*(n/5 + 1).wrap(0.5,2);
|
122
|
+
sound = HPF.ar(LPF.ar(WhiteNoise.ar(1), 3*frq), frq);
|
123
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp))
|
124
|
+
}).add
|
125
|
+
);
|
126
|
+
|
127
|
+
// Snare drum using Rumble-San's implementation as a starting point
|
128
|
+
// http://blog.rumblesan.com/post/53271713909/drum-sounds-in-supercollider-part-2
|
129
|
+
//
|
130
|
+
// "n" for some variation on frequency
|
131
|
+
// "decay" for scaling noise duration relative to tonal part
|
132
|
+
// "sustain" for overall timescale
|
133
|
+
// "accelerate" for tonal glide
|
134
|
+
(
|
135
|
+
SynthDef(\ssnare, {|out, sustain=1, pan=0, accelerate=0, n=60, decay=1, amp=1|
|
136
|
+
var env, sound, accel;
|
137
|
+
env = EnvGen.ar(Env.linen(0.01, 0, 0.6, 1, -3), timeScale:sustain, doneAction:2);
|
138
|
+
accel = Line.kr(1, 1+accelerate, 0.2);
|
139
|
+
sound = LPF.ar(Pulse.ar(100*accel*(n/5+1).wrap(0.5,2)), Line.ar(1030, 30, 0.2*sustain));
|
140
|
+
sound = sound + (BPF.ar(HPF.ar(WhiteNoise.ar(1), 500), 1500) * Line.ar(1, 0, 0.2*decay));
|
141
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp))
|
142
|
+
}).add
|
143
|
+
);
|
144
|
+
|
145
|
+
// Hand clap using Rumble-San's implementation as a starting point
|
146
|
+
// http://blog.rumblesan.com/post/53271713909/drum-sounds-in-supercollider-part-2
|
147
|
+
//
|
148
|
+
// "delay" controls the echo delay
|
149
|
+
// "speed" will affect the decay time
|
150
|
+
// "n" changes how spread is calculated
|
151
|
+
// "pitch1" will scale the bandpass frequency
|
152
|
+
// "sustain" the overall timescale
|
153
|
+
(
|
154
|
+
SynthDef(\sclap, {|out, speed=1, sustain=1, pan=0, n=60, delay=1, pitch1=1, amp=1|
|
155
|
+
var env, sound;
|
156
|
+
var spr = 0.005 * delay;
|
157
|
+
env = EnvGen.ar(Env.linen(0.01, 0, 0.6, 1, -3), timeScale:sustain, doneAction:2);
|
158
|
+
sound = BPF.ar(LPF.ar(WhiteNoise.ar(1), 7500*pitch1), 1500*pitch1);
|
159
|
+
sound = Mix.arFill(4, {arg i; sound * 0.5 * EnvGen.ar(Env.new([0,0,1,0],[spr*(i**(n.clip(0,5)+1)),0,0.04/speed]))});
|
160
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp))
|
161
|
+
}).add
|
162
|
+
);
|
163
|
+
|
164
|
+
// A controllable synth siren, defaults to 1 second, draw it out with "sustain"
|
165
|
+
(
|
166
|
+
SynthDef(\ssiren, {|out, sustain=1, pan=0, freq=440, amp=1|
|
167
|
+
var env, sound;
|
168
|
+
env = EnvGen.ar(Env.linen(0.05, 0.9, 0.05, 1, -2), timeScale:sustain, doneAction:2);
|
169
|
+
sound = VarSaw.ar(freq * (1.0 + EnvGen.kr(Env.linen(0.25,0.5,0.25,3,0), timeScale:sustain, doneAction:2)),
|
170
|
+
0, width:Line.kr(0.05,1,sustain));
|
171
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp))
|
172
|
+
}).add
|
173
|
+
);
|
174
|
+
|
175
|
+
// The next four synths respond to the following parameters in addition to
|
176
|
+
// gain, pan, n, and all the "effect" parameters (including attack, hold, and
|
177
|
+
// release). Default values in parentheses.
|
178
|
+
//
|
179
|
+
// sustain - scales overall duration
|
180
|
+
// decay(0) - amount of decay after initial attack
|
181
|
+
// accelerate(0) - pitch glide
|
182
|
+
// semitone(12) - how far off in pitch the secondary oscillator is (need not be integer)
|
183
|
+
// pitch1(1) - filter frequency scaling multiplier, the frequency itself follows the pitch set by "n"
|
184
|
+
// speed(1)- LFO rate
|
185
|
+
// lfo(1) - how much the LFO affects the filter frequency
|
186
|
+
// resonance(0.2) - filter resonance
|
187
|
+
// voice(0.5) - depends on the individual synth
|
188
|
+
|
189
|
+
// A moog-inspired square-wave synth; variable-width pulses with filter
|
190
|
+
// frequency modulated by an LFO
|
191
|
+
//
|
192
|
+
// "voice" controls the pulse width (exactly zero or one will make no sound)
|
193
|
+
(
|
194
|
+
SynthDef(\ssquare, {|out, speed=1, decay=0, sustain=1, pan=0, accelerate=0, freq=440,
|
195
|
+
voice=0.5, semitone=12, resonance=0.2, lfo=1, pitch1=1, amp=1|
|
196
|
+
var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2);
|
197
|
+
var basefreq = freq* Line.kr(1, 1+accelerate, sustain);
|
198
|
+
var basefreq2 = basefreq / (2**(semitone/12));
|
199
|
+
var lfof1 = min(basefreq*10*pitch1, 22000);
|
200
|
+
var lfof2 = min(lfof1 * (lfo + 1), 22000);
|
201
|
+
var sound = (0.7 * Pulse.ar(basefreq, voice)) + (0.3 * Pulse.ar(basefreq2, voice));
|
202
|
+
sound = MoogFF.ar(
|
203
|
+
sound,
|
204
|
+
SinOsc.ar(basefreq/64*speed, 0).range(lfof1,lfof2),
|
205
|
+
resonance*4);
|
206
|
+
sound = sound.tanh * 2;
|
207
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp));
|
208
|
+
}).add
|
209
|
+
);
|
210
|
+
|
211
|
+
// A moog-inspired sawtooth synth; slightly detuned saws with triangle
|
212
|
+
// harmonics, filter frequency modulated by LFO
|
213
|
+
//
|
214
|
+
// "voice" controls a relative phase and detune amount
|
215
|
+
(
|
216
|
+
SynthDef(\ssaw, {|out, speed=1, decay=0, sustain=1, pan=0, accelerate=0, freq=440,
|
217
|
+
voice=0.5, semitone=12, resonance=0.2, lfo=1, pitch1=1, amp=1|
|
218
|
+
var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2);
|
219
|
+
var basefreq = freq * Line.kr(1, 1+accelerate, sustain);
|
220
|
+
var basefreq2 = basefreq * (2**(semitone/12));
|
221
|
+
var lfof1 = min(basefreq*10*pitch1, 22000);
|
222
|
+
var lfof2 = min(lfof1 * (lfo + 1), 22000);
|
223
|
+
var sound = MoogFF.ar(
|
224
|
+
(0.5 * Mix.arFill(3, {|i| SawDPW.ar(basefreq * ((i-1)*voice/50+1), 0)})) + (0.5 * LFTri.ar(basefreq2, voice)),
|
225
|
+
LFTri.ar(basefreq/64*speed, 0.5).range(lfof1,lfof2),
|
226
|
+
resonance*4);
|
227
|
+
sound = sound.tanh*2;
|
228
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp));
|
229
|
+
}).add
|
230
|
+
);
|
231
|
+
|
232
|
+
// A moog-inspired PWM synth; pulses multiplied by phase-shifted pulses, double
|
233
|
+
// filtering with an envelope on the second.
|
234
|
+
//
|
235
|
+
// "voice" controls the phase shift rate
|
236
|
+
(
|
237
|
+
SynthDef(\spwm, {|out, speed=1, decay=0, sustain=1, pan=0, accelerate=0, freq=440,
|
238
|
+
voice=0.5, semitone=12, resonance=0.2, lfo=1, pitch1=1, amp=1|
|
239
|
+
var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2);
|
240
|
+
var env2 = EnvGen.ar(Env.pairs([[0,0.1],[0.1,1],[0.4,0.5],[0.9,0.2],[1,0.2]], -3), timeScale:sustain/speed);
|
241
|
+
var basefreq = freq * Line.kr(1, 1+accelerate, sustain);
|
242
|
+
var basefreq2 = basefreq / (2**(semitone/12));
|
243
|
+
var lfof1 = min(basefreq*10*pitch1, 22000);
|
244
|
+
var lfof2 = min(lfof1 * (lfo + 1), 22000);
|
245
|
+
var sound = 0.7 * PulseDPW.ar(basefreq) * DelayC.ar(PulseDPW.ar(basefreq), 0.2, Line.kr(0,voice,sustain)/basefreq);
|
246
|
+
sound = 0.3 * PulseDPW.ar(basefreq2) * DelayC.ar(PulseDPW.ar(basefreq2), 0.2, Line.kr(0.1,0.1+voice,sustain)/basefreq) + sound;
|
247
|
+
sound = MoogFF.ar(sound, SinOsc.ar(basefreq/32*speed, 0).range(lfof1,lfof2), resonance*4);
|
248
|
+
sound = MoogFF.ar(sound, min(env2*lfof2*1.1, 22000), 3);
|
249
|
+
sound = sound.tanh*5;
|
250
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp));
|
251
|
+
}).add
|
252
|
+
);
|
253
|
+
|
254
|
+
// This synth is inherently stereo, so handles the "pan" parameter itself and
|
255
|
+
// tells SuperDirt not to mix down to mono.
|
256
|
+
//
|
257
|
+
// "voice" scales the comparator frequencies, higher values will sound "breathier"
|
258
|
+
(
|
259
|
+
SynthDef(\scomparator, {|out, speed=1, decay=0, sustain=1, pan=0, accelerate=0, freq=440,
|
260
|
+
voice=0.5, resonance=0.5, lfo=1, pitch1=1, amp=1|
|
261
|
+
var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2);
|
262
|
+
var basefreq = freq * Line.kr(1, 1+accelerate, sustain);
|
263
|
+
var sound = VarSaw.ar(basefreq, 0, Line.ar(0,1,sustain));
|
264
|
+
var freqlist =[ 1.000, 2.188, 5.091, 8.529, 8.950, 9.305, 13.746, 14.653, 19.462, 22.003, 24.888, 25.991,
|
265
|
+
26.085, 30.509, 33.608, 35.081, 40.125, 42.023, 46.527, 49.481]**(voice/5);
|
266
|
+
sound = Splay.arFill(16, {|i| sound > LFTri.ar(freqlist[i])}, 1);
|
267
|
+
sound = MoogFF.ar(
|
268
|
+
sound,
|
269
|
+
pitch1 * 4 * basefreq + SinOsc.ar(basefreq/64*speed, 0, lfo*basefreq/2) + LFNoise2.ar(1,lfo*basefreq),
|
270
|
+
LFNoise2.ar(0,0.1,4*resonance));
|
271
|
+
sound = 0.5 * Balance2.ar(sound[0], sound[1], pan*2-1);
|
272
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, 0.5, amp));
|
273
|
+
}).add
|
274
|
+
);
|
275
|
+
|
276
|
+
// Uses the Atari ST emulation UGen with 3 oscillators
|
277
|
+
//
|
278
|
+
// "slide" is for a linear frequency glide that will repeat "speed" times (can
|
279
|
+
// be fractional or negative).
|
280
|
+
// "accelerate" is for an overall glide
|
281
|
+
// "pitch2" and "pitch3" control the ratio of harmonics
|
282
|
+
// "voice" causes variations in the levels of the 3 oscillators
|
283
|
+
(
|
284
|
+
SynthDef(\schip, {|out, sustain=1, pan=0, freq=440, speed=1, slide=0, pitch2=2, pitch3=3, accelerate=0, voice=0, amp=1|
|
285
|
+
var env, basefreq, sound, va, vb, vc;
|
286
|
+
env = EnvGen.ar(Env.linen(0.01, 0.98, 0.01,1,-1), timeScale:sustain, doneAction:2);
|
287
|
+
basefreq = freq + wrap2(slide * 100 * Line.kr(-1,1+(2*speed-2),sustain), slide * 100);
|
288
|
+
basefreq = basefreq * Line.kr(1, accelerate+1, sustain);
|
289
|
+
va = (voice < 0.5) * 15;
|
290
|
+
vb = ((2*voice) % 1 < 0.5) * 15;
|
291
|
+
vc = ((4*voice) % 1 < 0.5) * 15;
|
292
|
+
sound= AY.ar( AY.freqtotone(basefreq), AY.freqtotone(pitch2*basefreq), AY.freqtotone(pitch3*basefreq),
|
293
|
+
vola:va, volb:vb, volc:vc)/2;
|
294
|
+
sound = tanh(sound)*2;
|
295
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp));
|
296
|
+
}).add
|
297
|
+
);
|
298
|
+
|
299
|
+
// Digital noise in several flavors with a bandpass filter
|
300
|
+
//
|
301
|
+
// "voice" at 0 is a digital noise for which "n" controls rate, at 1 is
|
302
|
+
// Brown+White noise for which "n" controls knee frequency.
|
303
|
+
// "accelerate" causes glide in n, "speed" will cause it to repeat
|
304
|
+
// "pitch1" scales the bandpass frequency (which tracks "n")
|
305
|
+
// "slide" works like accelerate on the bandpass
|
306
|
+
// "resonance" is the filter resonance
|
307
|
+
(
|
308
|
+
SynthDef(\snoise, {|out, sustain=1, pan=0, freq=440, accelerate=0, slide=0, pitch1=1, speed=1, resonance=0, voice=0, amp=1|
|
309
|
+
var env, basefreq, sound, ffreq, acc;
|
310
|
+
env = EnvGen.ar(Env.linen(0.01, 0.98, 0.01,1,-1), timeScale:sustain, doneAction:2);
|
311
|
+
acc = accelerate * freq * 4;
|
312
|
+
basefreq = freq * 8 + wrap2(acc* Line.kr(-1,1+(2*speed-2), sustain), acc);
|
313
|
+
ffreq = basefreq*5*pitch1* Line.kr(1,1+slide, sustain);
|
314
|
+
ffreq = clip(ffreq, 60,20000);
|
315
|
+
sound = XFade2.ar( LFDNoise0.ar(basefreq.min(22000), 0.5),
|
316
|
+
XFade2.ar(BrownNoise.ar(0.5), WhiteNoise.ar(0.5), basefreq.cpsmidi/127),
|
317
|
+
2*voice-1);
|
318
|
+
sound = HPF.ar(BMoog.ar(sound, ffreq, resonance, 3), 20);
|
319
|
+
sound = clip(sound, -1,1) * 0.3;
|
320
|
+
OffsetOut.ar(out, Pan2.ar(sound * env, pan, amp));
|
321
|
+
}).add
|
322
|
+
);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xi-lang
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Damián Silvani
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -134,13 +134,15 @@ files:
|
|
134
134
|
- lib/xi/core_ext/array.rb
|
135
135
|
- lib/xi/core_ext/enumerable.rb
|
136
136
|
- lib/xi/core_ext/enumerator.rb
|
137
|
-
- lib/xi/core_ext/
|
137
|
+
- lib/xi/core_ext/integer.rb
|
138
138
|
- lib/xi/core_ext/numeric.rb
|
139
139
|
- lib/xi/core_ext/object.rb
|
140
140
|
- lib/xi/core_ext/scalar.rb
|
141
141
|
- lib/xi/core_ext/string.rb
|
142
142
|
- lib/xi/error_log.rb
|
143
143
|
- lib/xi/logger.rb
|
144
|
+
- lib/xi/osc.rb
|
145
|
+
- lib/xi/osc/version.rb
|
144
146
|
- lib/xi/pattern.rb
|
145
147
|
- lib/xi/pattern/generators.rb
|
146
148
|
- lib/xi/pattern/transforms.rb
|
@@ -148,8 +150,13 @@ files:
|
|
148
150
|
- lib/xi/scale.rb
|
149
151
|
- lib/xi/step_sequencer.rb
|
150
152
|
- lib/xi/stream.rb
|
153
|
+
- lib/xi/supercollider.rb
|
154
|
+
- lib/xi/supercollider/stream.rb
|
155
|
+
- lib/xi/supercollider/version.rb
|
151
156
|
- lib/xi/tidal_clock.rb
|
152
157
|
- lib/xi/version.rb
|
158
|
+
- synthdefs/other.scd
|
159
|
+
- synthdefs/superdirt.scd
|
153
160
|
- xi.gemspec
|
154
161
|
homepage: https://github.com/xi-livecode/xi
|
155
162
|
licenses:
|
@@ -170,8 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
177
|
- !ruby/object:Gem::Version
|
171
178
|
version: '0'
|
172
179
|
requirements: []
|
173
|
-
|
174
|
-
rubygems_version: 2.7.6
|
180
|
+
rubygems_version: 3.0.3
|
175
181
|
signing_key:
|
176
182
|
specification_version: 4
|
177
183
|
summary: Musical pattern language for livecoding
|
data/lib/xi/core_ext/fixnum.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
module Xi::CoreExt
|
2
|
-
module Fixnum
|
3
|
-
def /(o)
|
4
|
-
super(o.to_r)
|
5
|
-
end
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4')
|
10
|
-
class Fixnum
|
11
|
-
prepend Xi::CoreExt::Fixnum
|
12
|
-
end
|
13
|
-
else
|
14
|
-
class Integer
|
15
|
-
prepend Xi::CoreExt::Fixnum
|
16
|
-
end
|
17
|
-
end
|