xi-lang 0.1.4 → 0.1.5
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 +24 -11
- data/bin/xi +0 -1
- data/lib/xi/bjorklund.rb +60 -0
- data/lib/xi/clock.rb +9 -1
- data/lib/xi/core_ext/array.rb +13 -0
- data/lib/xi/core_ext/enumerable.rb +6 -14
- data/lib/xi/core_ext/enumerator.rb +14 -0
- data/lib/xi/core_ext/fixnum.rb +3 -3
- data/lib/xi/core_ext/numeric.rb +4 -4
- data/lib/xi/core_ext/scalar.rb +16 -0
- data/lib/xi/core_ext/string.rb +46 -44
- data/lib/xi/core_ext.rb +3 -1
- data/lib/xi/pattern/generators.rb +157 -162
- data/lib/xi/pattern/transforms.rb +96 -79
- data/lib/xi/pattern.rb +424 -95
- data/lib/xi/step_sequencer.rb +40 -0
- data/lib/xi/stream.rb +56 -64
- data/lib/xi/tidal_clock.rb +2 -1
- data/lib/xi/version.rb +1 -1
- data/lib/xi.rb +12 -3
- data/xi.gemspec +0 -1
- metadata +7 -18
- data/lib/xi/core_ext/simple.rb +0 -15
- data/lib/xi/event.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd3c1d2086dab411b68d702c8ca72ba9ba0875dc
|
4
|
+
data.tar.gz: 4a3ef7494c570a1990ae49a97a3f6d29371398cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 102013a3fb01d7764e83f9d5fa461ab430ef27153502e4f4b4bee5a1528001ef15660c0600ab1681f435defd615fdd7cd307b14958a7df0d7d2752ba7e5d3774
|
7
|
+
data.tar.gz: d94f330514d532fe1aa4de6d627ad7c8accf689f9e173fbdd4ba638d433f07c2a83db7edc081653c798a5ddfa41144e550313be4084ccc676f4a650dd3c5b39e
|
data/README.md
CHANGED
@@ -15,16 +15,25 @@ multiple known bugs, missing features, documentation and tests.
|
|
15
15
|
## Example
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
melody = [1,4,7,8,9]
|
19
|
+
scale = [Scale.iwato, Scale.jiao]
|
20
|
+
|
21
|
+
fm.set degree: melody.p(1/2,1/8,1/8,1/8,1/16,1/8,1/8).seq(2),
|
22
|
+
gate: :degree,
|
23
|
+
detune: [0.1, 0.4, 0.4],
|
24
|
+
sustain: [1,2,3,10],
|
25
|
+
accelerate: [0.5, 0, 0.1],
|
26
|
+
octave: [3,4,5,6].p(1/3),
|
27
|
+
scale: scale.p(1/2),
|
28
|
+
amp: P.new { |y| y << rand * 0.2 + 0.8 }.p(1/2)
|
29
|
+
|
30
|
+
kick.set freq: s("xi.x .ix. | xi.x xx.x", 70, 200), amp: 0.8, gate: :freq
|
31
|
+
|
32
|
+
clap.set n: s("..x. xyz. .x.. .xyx", 60, 61, 60).p.decelerate(2),
|
33
|
+
gate: :n,
|
34
|
+
amp: 0.35,
|
35
|
+
pan: P.sin(16, 2) * 0.6,
|
36
|
+
sustain: 0.25
|
28
37
|
```
|
29
38
|
|
30
39
|
## Installation
|
@@ -64,8 +73,9 @@ Then:
|
|
64
73
|
|
65
74
|
$ cd xi
|
66
75
|
$ bundle install
|
76
|
+
$ rake install
|
67
77
|
|
68
|
-
You're done! Fire up the REPL
|
78
|
+
You're done! Fire up the REPL using `xi`.
|
69
79
|
|
70
80
|
## Development
|
71
81
|
|
@@ -78,6 +88,9 @@ release a new version, update the version number in `version.rb`, and then run
|
|
78
88
|
git commits and tags, and push the `.gem` file to
|
79
89
|
[rubygems.org](https://rubygems.org).
|
80
90
|
|
91
|
+
You can also try things on the REPL without installing the gem on your machine
|
92
|
+
by doing `bundle exec bin/xi`.
|
93
|
+
|
81
94
|
## Contributing
|
82
95
|
|
83
96
|
Bug reports and pull requests are welcome on GitHub at
|
data/bin/xi
CHANGED
data/lib/xi/bjorklund.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Implementation adapted from Nebs' (MIT licensed)
|
2
|
+
# https://github.com/nebs/bjorklund-euclidean-rhythms
|
3
|
+
#
|
4
|
+
class Xi::Bjorklund
|
5
|
+
attr_reader :pulses, :slots, :value
|
6
|
+
|
7
|
+
def initialize(pulses, slots, value=nil)
|
8
|
+
@pulses = pulses.to_i
|
9
|
+
@slots = slots.to_i
|
10
|
+
@value = value || 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def p(*args, **metadata)
|
14
|
+
ary = to_a
|
15
|
+
ary.map { |v| v ? @value : nil }.p(1 / ary.size, **metadata)
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
"e(#{@pulses}, #{@slots}, #{@value.inspect})"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
to_a.map { |i| i ? 'x' : '.' }.join
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_a
|
27
|
+
k = @pulses
|
28
|
+
n = @slots
|
29
|
+
|
30
|
+
return [] if n == 0 || k == 0
|
31
|
+
|
32
|
+
bins = []
|
33
|
+
remainders = []
|
34
|
+
k.times { |i| bins[i] = [true] }
|
35
|
+
(n-k).times { |i| remainders[i] = [false] }
|
36
|
+
|
37
|
+
return bins.flatten if n == k
|
38
|
+
|
39
|
+
loop do
|
40
|
+
new_remainders = []
|
41
|
+
bins.each_with_index do |bin, i|
|
42
|
+
if remainders.empty?
|
43
|
+
new_remainders.push bin
|
44
|
+
else
|
45
|
+
bin += remainders.shift
|
46
|
+
bins[i] = bin
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if new_remainders.any?
|
51
|
+
bins.pop new_remainders.count
|
52
|
+
remainders = new_remainders
|
53
|
+
end
|
54
|
+
|
55
|
+
break unless remainders.size > 1
|
56
|
+
end
|
57
|
+
|
58
|
+
return (bins + remainders).flatten
|
59
|
+
end
|
60
|
+
end
|
data/lib/xi/clock.rb
CHANGED
@@ -64,6 +64,14 @@ module Xi
|
|
64
64
|
@mutex.synchronize { 1.0 / @cps }
|
65
65
|
end
|
66
66
|
|
67
|
+
def current_time
|
68
|
+
Time.now.to_f - @init_ts + @latency
|
69
|
+
end
|
70
|
+
|
71
|
+
def current_cycle
|
72
|
+
current_time * cps
|
73
|
+
end
|
74
|
+
|
67
75
|
def inspect
|
68
76
|
"#<#{self.class.name}:#{"0x%014x" % object_id} " \
|
69
77
|
"cps=#{cps.inspect} #{playing? ? :playing : :stopped}>"
|
@@ -80,7 +88,7 @@ module Xi
|
|
80
88
|
|
81
89
|
def do_tick
|
82
90
|
return unless playing?
|
83
|
-
now
|
91
|
+
now = self.current_time
|
84
92
|
cps = self.cps
|
85
93
|
@streams.each { |s| s.notify(now, cps) }
|
86
94
|
rescue => err
|
@@ -1,25 +1,17 @@
|
|
1
1
|
require 'xi/pattern'
|
2
2
|
|
3
|
-
module Xi
|
4
|
-
module
|
5
|
-
def p(
|
6
|
-
Pattern.new(self,
|
3
|
+
module Xi::CoreExt
|
4
|
+
module Enumerable
|
5
|
+
def p(*delta, **metadata)
|
6
|
+
Xi::Pattern.new(self.to_a, delta: delta, **metadata)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
class Enumerator
|
12
|
-
include Xi::
|
13
|
-
end
|
14
|
-
|
15
|
-
class Array
|
16
|
-
include Xi::Pattern::Enumerable
|
17
|
-
end
|
18
|
-
|
19
|
-
class Hash
|
20
|
-
include Xi::Pattern::Enumerable
|
12
|
+
include Xi::CoreExt::Enumerable
|
21
13
|
end
|
22
14
|
|
23
15
|
class Range
|
24
|
-
include Xi::
|
16
|
+
include Xi::CoreExt::Enumerable
|
25
17
|
end
|
data/lib/xi/core_ext/fixnum.rb
CHANGED
data/lib/xi/core_ext/numeric.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Xi
|
1
|
+
module Xi::CoreExt
|
2
2
|
module Numeric
|
3
3
|
def midi_to_cps
|
4
4
|
440 * (2 ** ((self - 69) / 12.0))
|
@@ -22,13 +22,13 @@ module Xi
|
|
22
22
|
end
|
23
23
|
|
24
24
|
class Fixnum
|
25
|
-
include Xi::Numeric
|
25
|
+
include Xi::CoreExt::Numeric
|
26
26
|
end
|
27
27
|
|
28
28
|
class Float
|
29
|
-
include Xi::Numeric
|
29
|
+
include Xi::CoreExt::Numeric
|
30
30
|
end
|
31
31
|
|
32
32
|
class Rational
|
33
|
-
include Xi::Numeric
|
33
|
+
include Xi::CoreExt::Numeric
|
34
34
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'xi/pattern'
|
2
|
+
|
3
|
+
module Xi::CoreExt
|
4
|
+
module Scalar
|
5
|
+
def p(*delta, **metadata)
|
6
|
+
[self].p(*delta, **metadata)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Fixnum; include Xi::CoreExt::Scalar; end
|
12
|
+
class Float; include Xi::CoreExt::Scalar; end
|
13
|
+
class String; include Xi::CoreExt::Scalar; end
|
14
|
+
class Symbol; include Xi::CoreExt::Scalar; end
|
15
|
+
class Rational; include Xi::CoreExt::Scalar; end
|
16
|
+
class Hash; include Xi::CoreExt::Scalar; end
|
data/lib/xi/core_ext/string.rb
CHANGED
@@ -1,50 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
1
|
+
module Xi::CoreExt
|
2
|
+
# String Inflectors, taken from ActiveSupport 5.0 source code
|
3
|
+
module String
|
4
|
+
# Converts strings to UpperCamelCase.
|
5
|
+
# If the +uppercase_first_letter+ parameter is set to false, then produces
|
6
|
+
# lowerCamelCase.
|
7
|
+
#
|
8
|
+
# Also converts '/' to '::' which is useful for converting
|
9
|
+
# paths to namespaces.
|
10
|
+
#
|
11
|
+
# camelize('active_model') # => "ActiveModel"
|
12
|
+
# camelize('active_model', false) # => "activeModel"
|
13
|
+
# camelize('active_model/errors') # => "ActiveModel::Errors"
|
14
|
+
# camelize('active_model/errors', false) # => "activeModel::Errors"
|
15
|
+
#
|
16
|
+
# As a rule of thumb you can think of +camelize+ as the inverse of
|
17
|
+
# #underscore, though there are cases where that does not hold:
|
18
|
+
#
|
19
|
+
# camelize(underscore('SSLError')) # => "SslError"
|
20
|
+
def camelize
|
21
|
+
string = self.sub(/^[a-z\d]*/) { |match| match.capitalize }
|
22
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
23
|
+
string.gsub!('/'.freeze, '::'.freeze)
|
24
|
+
string
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
27
|
+
# Makes an underscored, lowercase form from the expression in the string.
|
28
|
+
#
|
29
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
30
|
+
#
|
31
|
+
# underscore('ActiveModel') # => "active_model"
|
32
|
+
# underscore('ActiveModel::Errors') # => "active_model/errors"
|
33
|
+
#
|
34
|
+
# As a rule of thumb you can think of +underscore+ as the inverse of
|
35
|
+
# #camelize, though there are cases where that does not hold:
|
36
|
+
#
|
37
|
+
# camelize(underscore('SSLError')) # => "SslError"
|
38
|
+
def underscore
|
39
|
+
return self unless self =~ /[A-Z-]|::/
|
40
|
+
word = self.to_s.gsub('::'.freeze, '/'.freeze)
|
41
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze)
|
42
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze)
|
43
|
+
word.tr!("-".freeze, "_".freeze)
|
44
|
+
word.downcase!
|
45
|
+
word
|
46
|
+
end
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
50
|
class String
|
49
|
-
include Xi::
|
51
|
+
include Xi::CoreExt::String
|
50
52
|
end
|
data/lib/xi/core_ext.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'xi/core_ext/array'
|
1
2
|
require 'xi/core_ext/enumerable'
|
3
|
+
require 'xi/core_ext/enumerator'
|
2
4
|
require 'xi/core_ext/fixnum'
|
3
5
|
require 'xi/core_ext/numeric'
|
4
6
|
require 'xi/core_ext/object'
|
5
|
-
require 'xi/core_ext/
|
7
|
+
require 'xi/core_ext/scalar'
|
6
8
|
require 'xi/core_ext/string'
|