Class: Xi::Pattern
- Extended by:
- Generators
- Includes:
- Transforms
- Defined in:
- lib/xi/pattern.rb,
lib/xi/pattern/generators.rb,
lib/xi/pattern/transforms.rb
Overview
A Pattern is a lazy, infinite enumeration of values in time.
An event represents a value that occurs in a specific moment in time. It is a value together with its onset (start position) in terms of cycles, and its duration. It is usually represented by a tuple of (value, start, duration, iteration). This tuple indicates when a value occurs in time (start), its duration, and on which iteration of the pattern happens.
P is an alias of Pattern, so you can build them using P instead. Note that if the pattern was built from an array, the string representation can be used to build the same pattern again (almost the same ignoring whitespace between constructor arguments).
P[1,2,3] #=> P[1, 2, 3]
Defined Under Namespace
Modules: Generators, Transforms Classes: EventEnumerator
Instance Attribute Summary collapse
-
#delta ⇒ Object
readonly
Event delta in terms of cycles (default: 1).
-
#duration ⇒ Object
readonly
Duration of pattern.
-
#metadata ⇒ Object
readonly
Hash that contains metadata related to pattern usage.
-
#size ⇒ Object
readonly
Size of pattern.
-
#source ⇒ Object
readonly
Array or Proc that produces values or events.
Class Method Summary collapse
-
.[](*args, **kwargs) ⇒ Pattern
Create a new Pattern given an array of
args.
Instance Method Summary collapse
- #==(o) ⇒ Object
-
#each {|Object| ... } ⇒ Enumerator
Calls the given block once for each value in source.
-
#each_delta(index = 0) {|d| ... } ⇒ Enumerator
Calls the given block passing the delta of each value in pattern.
-
#each_event(cycle = 0) {|v, s, d, i| ... } ⇒ Enumerator
Calls the given block once for each event, passing its value, start position, duration and iteration as parameters.
-
#finite? ⇒ Boolean
Returns true if pattern is finite.
-
#first(n = nil, *args) ⇒ Object, Array
Returns the first element, or the first
nelements, of the pattern. -
#infinite? ⇒ Boolean
Returns true if pattern is infinite.
-
#initialize(source = nil, size: nil, delta: nil, **metadata) {|yielder, delta| ... } ⇒ Pattern
constructor
Creates a new Pattern given either a
sourceor ablockthat yields events. -
#inspect ⇒ String
(also: #to_s)
Returns a string containing a human-readable representation.
-
#iteration_size ⇒ Integer
Returns pattern interation size or length.
-
#map {|v, s, d, i| ... } ⇒ Pattern
(also: #collect)
Returns a new Pattern with the results of running
blockonce for every value inself. -
#p(*delta, **metadata) ⇒ Pattern
Returns a new Pattern with the same
source, but withdeltaoverriden andmetadatamerged. - #peek(n = 10, *args) ⇒ Object
- #peek_events(n = 10, cycle = 0) ⇒ Object
-
#reject {|v, s, d, i| ... } ⇒ Pattern
Returns a Pattern containing all events of
selffor whichblockis false. -
#reverse_each {|Object| ... } ⇒ Enumerator
Same as #each but in reverse order.
-
#select {|v, s, d, i| ... } ⇒ Pattern
(also: #find_all)
Returns a Pattern containing all events of
selffor whichblockis true. -
#take(n, cycle = 0) ⇒ Array
Returns the first
nevents from the pattern, starting fromcycle. -
#take_values(*args) ⇒ Object
Returns the first
nvalues fromself, starting fromcycle. -
#to_a ⇒ Array
Returns an array of values from a single iteration of pattern.
-
#to_events ⇒ Array
Returns an array of events (i.e. a tuple [value, start, duration, iteration]) from the first iteration.
Methods included from Generators
geom, isaw, rand, saw, series, shuf, sin, tri, xrand
Methods included from Transforms
#%, #*, #**, #+, #-, #-@, #/, #bounce, #denormalize, #every, #every_iter, #fast, #normalize, #rand, #repeat_each, #scale, #seq, #shuf, #slow, #sometimes, #when, #xrand
Constructor Details
#initialize(source = nil, size: nil, delta: nil, **metadata) {|yielder, delta| ... } ⇒ Pattern
Creates a new Pattern given either a source or a block that yields events.
If a block is given, yielder parameter must yield value and start (optional) for each event.
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 |
# File 'lib/xi/pattern.rb', line 69 def initialize(source=nil, size: nil, delta: nil, **, &block) if source.nil? && block.nil? fail ArgumentError, 'must provide source or block' end if delta && delta.respond_to?(:size) && !(delta.size < Float::INFINITY) fail ArgumentError, 'delta cannot be infinite' end # If delta is an array of 1 or 0 values, flatten array delta = delta.first if delta.is_a?(Array) && delta.size <= 1 # Block takes precedence as source, even though +source+ can be used to # infer attributes @source = block || source # Infer attributes from +source+ if it is a pattern if source.is_a?(Pattern) @delta = source.delta @size = source.size @metadata = source. else @delta = 1 @size = (source.respond_to?(:size) ? source.size : nil) || Float::INFINITY @metadata = {} end # Flatten source if it is a pattern @source = @source.source if @source.is_a?(Pattern) # Override or merge custom attributes if they were specified @size = size if size @delta = delta if delta @metadata.merge!() # Flatten delta values to an array, if it is an enumerable or pattern @delta = @delta.to_a if @delta.respond_to?(:to_a) # Set duration based on delta values @duration = delta_values.reduce(:+) || 0 end |
Instance Attribute Details
#delta ⇒ Object (readonly)
Event delta in terms of cycles (default: 1)
28 29 30 |
# File 'lib/xi/pattern.rb', line 28 def delta @delta end |
#duration ⇒ Object (readonly)
Duration of pattern
37 38 39 |
# File 'lib/xi/pattern.rb', line 37 def duration @duration end |
#metadata ⇒ Object (readonly)
Hash that contains metadata related to pattern usage
31 32 33 |
# File 'lib/xi/pattern.rb', line 31 def @metadata end |
#size ⇒ Object (readonly)
Size of pattern
34 35 36 |
# File 'lib/xi/pattern.rb', line 34 def size @size end |
#source ⇒ Object (readonly)
Array or Proc that produces values or events
25 26 27 |
# File 'lib/xi/pattern.rb', line 25 def source @source end |
Class Method Details
.[](*args, **kwargs) ⇒ Pattern
Create a new Pattern given an array of args
120 121 122 |
# File 'lib/xi/pattern.rb', line 120 def self.[](*args, **kwargs) new(args, **kwargs) end |
Instance Method Details
#==(o) ⇒ Object
430 431 432 433 434 435 436 437 |
# File 'lib/xi/pattern.rb', line 430 def ==(o) self.class == o.class && delta == o.delta && size == o.size && duration == o.duration && == o. && (finite? && to_a == o.to_a) end |
#each {|Object| ... } ⇒ Enumerator
Calls the given block once for each value in source
241 242 243 244 245 246 247 248 |
# File 'lib/xi/pattern.rb', line 241 def each return enum_for(__method__) unless block_given? each_event { |v, _, _, i| break if i > 0 yield v } end |
#each_delta(index = 0) {|d| ... } ⇒ Enumerator
Calls the given block passing the delta of each value in pattern
This method is used internally by #each_event to calculate when each event in pattern occurs in time. If no block is given, an Enumerator is returned instead.
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/xi/pattern.rb', line 209 def each_delta(index=0) return enum_for(__method__, index) unless block_given? delta = @delta if delta.is_a?(Array) size = delta.size return if size == 0 start = index.floor i = start % size loop do yield delta[i] i = (i + 1) % size start += 1 end elsif delta.is_a?(Pattern) delta.each_event(index) { |v, _| yield v } else loop { yield delta } end end |
#each_event(cycle = 0) {|v, s, d, i| ... } ⇒ Enumerator
Calls the given block once for each event, passing its value, start position, duration and iteration as parameters.
cycle can be any number, even if there is no event that starts exactly at that moment. It will start from the next event.
If no block is given, an enumerator is returned instead.
Enumeration loops forever, and starts yielding events based on pattern’s delta and from the cycle position, which is by default 0.
194 195 196 197 |
# File 'lib/xi/pattern.rb', line 194 def each_event(cycle=0) return enum_for(__method__, cycle) unless block_given? EventEnumerator.new(self, cycle).each { |v, s, d, i| yield v, s, d, i } end |
#finite? ⇒ Boolean
Returns true if pattern is finite
A pattern is finite if it has a finite size.
155 156 157 |
# File 'lib/xi/pattern.rb', line 155 def finite? !infinite? end |
#first(n = nil, *args) ⇒ Object, Array
Returns the first element, or the first n elements, of the pattern.
If the pattern is empty, the first form returns nil, and the second form returns an empty array.
387 388 389 390 |
# File 'lib/xi/pattern.rb', line 387 def first(n=nil, *args) res = take(n || 1, *args) n.nil? ? res.first : res end |
#infinite? ⇒ Boolean
Returns true if pattern is infinite
A Pattern is infinite if it was created from a Proc or another infinite pattern, and size was not specified.
144 145 146 |
# File 'lib/xi/pattern.rb', line 144 def infinite? @size == Float::INFINITY end |
#inspect ⇒ String Also known as: to_s
Returns a string containing a human-readable representation
When source is not a Proc, this string can be evaluated to construct the same instance.
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/xi/pattern.rb', line 399 def inspect ss = if @source.respond_to?(:join) @source.map(&:inspect).join(', ') elsif @source.is_a?(Proc) "?proc" else @source.inspect end ms = @metadata.reject { |_, v| v.nil? } ms.merge!(delta: delta) if delta != 1 ms = ms.map { |k, v| "#{k}: #{v.inspect}" }.join(', ') "P[#{ss}#{", #{ms}" unless ms.empty?}]" end |
#iteration_size ⇒ Integer
Returns pattern interation size or length
This is usually calculated from the least-common multiple between the sum of delta values and the size of the pattern. If pattern is infinite, pattern size is assumed to be 1, so iteration size depends on delta values.
425 426 427 |
# File 'lib/xi/pattern.rb', line 425 def iteration_size finite? ? delta_size.lcm(@size) : delta_size end |
#map {|v, s, d, i| ... } ⇒ Pattern Also known as: collect
Returns a new Pattern with the results of running block once for every value in self
If no block is given, an Enumerator is returned.
296 297 298 299 300 301 302 303 304 |
# File 'lib/xi/pattern.rb', line 296 def map return enum_for(__method__) unless block_given? Pattern.new(self) do |y, d| each_event do |v, s, ed, i| y << yield(v, s, ed, i) end end end |
#p(*delta, **metadata) ⇒ Pattern
Returns a new Pattern with the same source, but with delta overriden and metadata merged.
131 132 133 134 |
# File 'lib/xi/pattern.rb', line 131 def p(*delta, **) delta = delta.compact.empty? ? @delta : delta Pattern.new(@source, delta: delta, size: @size, **@metadata.merge()) end |
#peek(n = 10, *args) ⇒ Object
367 368 369 |
# File 'lib/xi/pattern.rb', line 367 def peek(n=10, *args) take_values(n, *args) end |
#peek_events(n = 10, cycle = 0) ⇒ Object
372 373 374 |
# File 'lib/xi/pattern.rb', line 372 def peek_events(n=10, cycle=0) take(n, cycle) end |
#reject {|v, s, d, i| ... } ⇒ Pattern
Returns a Pattern containing all events of self for which block is false.
If no block is given, an Enumerator is returned.
340 341 342 343 344 |
# File 'lib/xi/pattern.rb', line 340 def reject return enum_for(__method__) unless block_given? select { |v, s, d, i| !yield(v, s, d, i) } end |
#reverse_each {|Object| ... } ⇒ Enumerator
Same as #each but in reverse order
259 260 261 262 |
# File 'lib/xi/pattern.rb', line 259 def reverse_each return enum_for(__method__) unless block_given? each.to_a.reverse.each { |v| yield v } end |
#select {|v, s, d, i| ... } ⇒ Pattern Also known as: find_all
Returns a Pattern containing all events of self for which block is true.
If no block is given, an Enumerator is returned.
318 319 320 321 322 323 324 325 326 |
# File 'lib/xi/pattern.rb', line 318 def select return enum_for(__method__) unless block_given? Pattern.new(self) do |y, d| each_event do |v, s, ed, i| y << v if yield(v, s, ed, i) end end end |
#take(n, cycle = 0) ⇒ Array
Returns the first n events from the pattern, starting from cycle
352 353 354 |
# File 'lib/xi/pattern.rb', line 352 def take(n, cycle=0) each_event(cycle).take(n) end |
#take_values(*args) ⇒ Object
Returns the first n values from self, starting from cycle.
Only values are returned, start position and duration are ignored.
362 363 364 |
# File 'lib/xi/pattern.rb', line 362 def take_values(*args) take(*args).map(&:first) end |
#to_a ⇒ Array
Returns an array of values from a single iteration of pattern
269 270 271 272 |
# File 'lib/xi/pattern.rb', line 269 def to_a fail StandardError, 'pattern is infinite' if infinite? each.to_a end |
#to_events ⇒ Array
Returns an array of events (i.e. a tuple [value, start, duration, iteration]) from the first iteration.
Only applies to finite patterns.
282 283 284 285 |
# File 'lib/xi/pattern.rb', line 282 def to_events fail StandardError, 'pattern is infinite' if infinite? each_event.take(size) end |