-
Notifications
You must be signed in to change notification settings - Fork 5
Enumerables
Enumberables are something that can be calculated and played on the fly (which is more fun). Ziffers has some built in methods for calculating sequences such as continued fractions of Pi or triangular sums.
You can also create your own number sequences, so if you happen to know a mathematic formula for creating the perfect melody it is relatively easy to try it out :)
Number sequences are any number of numbers that creates a finite or infinite sequence.
Consider a number 369420. This number can be played sequantially as a melody or concurrently as a chord. It can also be played in any key or scale and added some rhythmic variation based on taste or some mathematical relations between the numbers. By default integers are played sequantially. To play integer as a chord use parse_chords: true parameter.
Then consider a sequence of numbers 6 18 54 162 486 1458 4374. These numbers again could be played in different ways. These sets of numbers can also be transformed, added, divided, etc. and the base of the numbers can be changed for example from 10 to 6. Number sequences can also be considered as a string that can be modified with rules.
Examples of combining rhythm with the number sequences:
zplay pi, rhythm: "s s e e"*2+"q e e"*2+"e s s e e"*2 # This will take some time to finish...
zplay reverse_sum(589865754), rhythm: {0=>"e", 1=>"s",2=>"s",3=>"q",4=>"s",5=>"e",6=>"e", 7=>"s",8=>"e",9=>"s"}
Enumerables can also be used as parallel loops. Here euler meets pi:
r_map = {0=>"e", 1=>"s",2=>"s",3=>"q",4=>"s",5=>"e",6=>"e", 7=>"s",8=>"e",9=>"s"}
z1 euler, rhythm: r_map , key: :c3, synth: :chiplead # Synth options can be modified on the fly
z2 pi, rhythm: r_map, key: :c3, synth: :chipbass
Or some very mathy jazz:
z1 bruijn, duration: ->(i){i%rrand_i(3,6)==0 ? 0.0625 : 0.125}, scale: :blues_major, synth: :tri, amp: 0.5, release: 0.1, attack: 0.1, decay: 0.1
z2 bruijn_walk, duration: 0.125, key: :c3, synth: :fm
Custom enumerables can be created using Ruby's enumerations.
There couple of ways of creating enumerations. Using ranges and lazy enumerations:
# To infinity and beyond!
sums = (1..Float::INFINITY).lazy.collect {|x| (x*x)}
zplay sums, parse_chords: false, duration: 0.125
Or by creating enumerations using Enumeration class:
def awesomeness(n=20,variance=3)
mem = [rrand_i(0,7)]
Enumerator.new do |y|
until mem.length>=n do
mem = mem.zip(mem.map{|n| n+rrand_i(-variance, variance)}).flatten
y << mem.join(" ")
end
print "Reached the end of enum!"
end
end
# Loop cycles the finite enumerations
z1 awesomeness, rhythm: "e s s", release: 0.1
There are many beautiful and intrigue integer sequences with musical properties out there. Best place to search for them is OEIS encyclopedia using hear keyword.
All sequence generators are implemented as ruby enumerators, which can be played directly using zplay or looped in various ways, for example:
print recaman.take(10)
e = recaman
10.times do
print e.next
end
Here is a list of sequences that are implemented as enumerations:
Sequence in OEIS: A000045
# Play fibonacci numbers as chords
zplay fibonacci, duration: 0.25
Sequence in OEIS: A000040
# Play primes as chords until 500
zplay primes(500), duration: 0.25
# Play primes as chords until memory runs out
zplay primes, duration: 0.25
Cool self similar sequence. Sequence in OEIS: https://oeis.org/A000695
n = bruijn.take(30)
v = n.map {|n| n.to_s.split("") }.join(" ")
zplay v, duration: 0.25, synth: :piano
Nice walking bass sequence based on bruijn. Sequence in OEIS: https://oeis.org/A059905
n = bruijn_walk.take(30)
v = n.map {|n| n.to_s.split("") }.join(" ")
zplay v, duration: 0.25, synth: :piano, octave: -2
Morse Thue sequence is propably the mostly used sequence in fractal music.
Sequence in OEIS: https://oeis.org/A010060
print thue_morse.take(100).to_a
Morse Thue sequence can be used to generate number sequences in any base (only defaults to binary):
melody = thue_morse(6).take(100).to_a
rhythm = thue_morse(3).take(16).to_a
zplay melody, synth: :piano, scale: :egyptian, rhythm: rhythm
Alternatively sequence can be counted in binary and modded to spesified range using second parameter:
mt_scale = scalenator(thue_morse.take(100).to_a)
mt_melody = thue_morse(2,7)
mt_rhythm = thue_morse(4).take(16).to_a
zplay mt_melody, scale: mt_scale, rhythm: mt_rhythm, synth: :dark_ambience, ring: 0.9, room: tweak(:sine,2,20,10).mirror, reverb_time: 100
Well ... still sounds like crap but maybe you can make something interesting out of it.
Numberphile video about the sequence: https://www.youtube.com/watch?v=etMJxB-igrc&t=422s Sequence in OEIS: http://oeis.org/A181391
# Getting first 100 from the sequence
n = vanecks.take(100)
print n
Playing sequence directly with some rhythm mapping:
use_bpm 200
z1 vanecks, rhythm: "qee", synth: :piano
Video about the sequence in Numberphile: https://www.youtube.com/watch?v=rBU9E-ZOZAI Sequence in OEIS: http://oeis.org/A342585
# Getting first 100 from the sequence
n = inventory.take(100)
print n
Playing sequence directly with some rhythm mapping:
use_bpm 170
z1 inventory, rhythm: {0=>"s",1=>"e",2=>"e.",2=>"q"}, synth: :chiplead
# Play recaman sequence
zplay recaman, duration: 0.25, synth: :hollow, release: 2.0
Sequence in OEIS: A005185
zplay hoffQ, duration: 0.25, parse_chords: false, scale: :minor, rhythm: "eeqq"*2+"h q q"*2+"q e e q q"*2
Sequence in OEIS: A002487
zplay sterns, duration: 0.25, scale: :harmonic_minor
Sequence in OEIS: A001316
zplay dress, synth: :chipbass, key: :d3, scale: :minor_pentatonic, rhythm: "eeqh"
Sequence in OEIS: A000265
zplay frac2, duration: 0.25
Sequence in OEIS: A030101
Optional parameter base, default=2.
zplay binrev, duration: 0.25
Reverse sum of some numbers creates symmetric patterns. Idea from MathPages.
Optional parameter base, default=10
zplay reverse_sum(313), synth: :fm, parse_chords: false, rhythm: "q q h"
Collatz conjecture will create a number sequence that will eventually lead to 1.
zplay (collatz 987654321), parse_chords: false, rhythm: "qqeeee"
Sequence in OEIS: A000217
# Plays chords from triangular number sequence
zplay triangular, duration: 0.25
# Play values of y as chords
z1 quadratic(1,100,1,-10,20), duration: 0.2
Create your own Arithemitc progression.
zplay aprog(1,4,5), duration: 0.25
print "Done!"
# This one goes forever
zplay aprog(1,4), duration: 0.25
Create your own Geometric progression.
zplay gprog(3,4,5), duration: 0.25
print "Done!"
# This one goes forever
zplay gprog(3,4), duration: 0.25
Infinite Continued fraction is a number sequence like pi or square root of 2. Continued fractions can be calculated using for example general infinite continued fraction algorithm, which was used for enumerables pi, phi and euler.
Everybody loves π. Now you can listen to it forever (until your computer crashes).
Sequence in OEIS: A000796
z1 pi, rhythm: [0.125,0.125,0.25], synth: :winwood_lead, release: ->(){rrand(0.01,0.5)}, res: 0.1, attack: ->(){rrand(0.01,0.5)}
Sequence in OEIS: A001622
z1 phi, rhythm: "eeqq"*2+"h q q"*2+"q e e q q"*2
Sequence in OEIS: A001113
z1 euler, duration: 0.25, synth: :organ_tonewheel, amp: 0.5, tierce: 3.0, fundamental: 2.0, larigot: 2.0
Cellular automata is implemented as enumerations where indexes of dead or live cells are interpeted as pitches in the given scale.
First generation can be inputted as a boolean array, boolean string and also a integer or string that is interpreted as binary.
There are 255 rules for elementary automata, which can be changed as a second parameter (random between 1-255 if omitted). See wiki for behaviour of different rules:
# First parameter: Starting generation, Second parameter: Rule number
zplay (live_cells spread(3,7), 23), rhythm: "qee" # First generation: "1010100"
zplay (live_cells 235, 23), rhythm: "qeeh" # First generation: 11101011"
zplay (dead_cells "001010001010", 23), rhythm: "qeeh" # First generation: "1010001010"
zplay (dead_cells "quuquubaba", 23), rhythm: "qeeh" # First generation: "011100010..."
Cellular automata can also output booleans with boolean_automata method. These booleans can be interpreted as melody and rhythm in various ways, for example using bools_to_seq method:
# First param is turned into binary, second param is the rule number
a = boolean_cells "Answer to Life, the Universe and Everything", 42
s = a.take(1000)
b = bools_to_seq(s)
zplay b, rhythm: b, synth: :hollow, sustain: 0.25, scale: :mixolydian
There are two type of markov chains implemented. Markov generator and markov analyzer.
Markov generator interprets integers (or hex strings) as markov chains. Input is interpreted as infinite chain, for example: 123 = 1 -> 2 -> 3 -> 1. More transitions between numbers will cause higher propability of changes, for example: 12344444444324, will repeat 4 more than the other numbers:
zplay (markov_generator 12345), duration: 0.25
zplay markov_generator("034A34F3562G3"), rhythm: "hqq"*2+"qqeeee"*2
Markov analyzer can create chains from existing melody:
m = zparse "q. 0 0 | q0 e1 q.2 | q2 e1 q2 e3 | h.4 | e 7 7 7 4 4 4 2 2 2 0 0 0 | q4 e3 q2 e1 | h. 0 "
zplay markov_analyzer m, 2, 0 # Paremeters: parsed melody, chain order, starting index
------------------------------------ See more stuff from the menu --------------------------------------->