Skip to content

Transformations

Miika Alonen edited this page Feb 1, 2022 · 34 revisions

Transforming melodies

Melody transformations alter the parsed melody. Transformations can be done to parsed melodies or used directly with zplay or zloop.

Transforming parsed melodies:

use_synth :piano

a = zparse "q 0 2 1 4"

b = a.invert

c = a.retrograde

d = a.invert.retrograde

e = a.transpose -3

zplay (a*2+b*2+c*2+d*2+b+e)*2

Transformations can also be executed with cycle specific options using using cycle or by using lambdas:

z1 "q 0 1 2 3", cycle: {at: 2, harmonize: 3 }
z2 "q 3 2 1 0", release:->(i){i%3} # i / first parameter is interpreted as the loop cycle

Transformations can also be stored to the next cycles of the loop using store: true:

z1 "q 0 1 e 2 3 4 5", store: true, swap:->(i){i}

There are three types of transformations: Order transformations, object transformations and loop transformations.

Order transformations

Order tranformations are always run before object tranformations. These type of transformations alter the whole or part of the melody before any notes are played. There can be multiple order transformations which are run in order from left to right.

Retrograde

Inverses the melody while keeping the chords in place. Use retrograde: true to inverse the whole melody.

Partial melody retrograde: [2,4] where first value is the start index and last valie is the end index.

Splitted melody retrograde: 3 where value is the number of parts the melody is splitted before the reverse.

zplay "i 1 2 vi%-2 3 4", chord_sleep: 0, retrograde: true
zplay "0 1 2 3 4 5", retrograde: [0,1]
zplay "0 1 2 3 4 5", retrograde: 2

Reverse

Reverses melody including the chords.

zplay "i 1 2 vi%-2 3 4", chord_sleep: 0, reverse: true
zplay "0 1 2 3", reverse: true

Rotate

Rotate the melody

zplay "0 1 2 3 4", rotate: 1
zplay "0 1 2 3 4", rotate: -1
z1 "0 1 2 3 4", store: true, rotate: 1

Swap

Swap places of degrees (and notes) in a melody. Swap in

zplay "0 1 2 3", swap: 1 # Creates 0 1 2 3
zplay "0 1 2 3", swap: [1,3] # Creates 0 1 2 3
z1 "0 1 2 3", store:true, swap: ->(i){i}

Group by division

Groups the melody using mod

z1 "q 0 1 2 3 4 5 6", division: 2

Mirror

Creates mirror from the melody

zplay "0 1 2 3", mirror: true

Reflect

Creates reflection from the melody

zplay "0 1 2 3", reflect: true

Rotate

Rotates the melody

zplay "0 1 2 3", rotate: 1
zplay "0 1 2 3", rotate: 2
zplay "0 1 2 3", rotate: -1
z1 "0 1 2 3 4", store: true, rotate: 1 # Stores the rotation for the next cycle

Subset

Creates subset from the melody

zplay "0 1 2 3 4 5", subset: 3
zplay "0 1 2 3 4 5", subset: 1..2

Inject

Augments the melody by injecting intervals. Bit esoteric at the moment.

zplay "q 0 1", inject: "q 1 2 3 4"

Zip

Zip will merge another melody to existing one. Zip works like a "zipper" and omits extra notes that cannot be "zipped".

zplay "0 1 2", zip: "3 4 5" # Plays 0 3 1 4 2 5
zplay "0 1", zip: "6 7 8" # Plays 0 6 1 7

Append

Appends new notes to melody

zplay "q 0 1", append: "e 8 4" # Plays q 0 1 e 8 4

Prepend

Prepends new notes to melody

zplay "q 0 1", prepend: "e 8 4" # Plays e 8 4 q 0 1

Shuffle

Randomizes the melody or part of the melody

zplay "q 0 1 2 3 4", shuffle: true
z1 "q 0 1 2 3 4", shuffle: 2..3

Drop

Drops a note or set of notes from a melody

zplay "q 0 1 2 3 4", drop: 2
zplay "q 0 1 2 3 4", drop: 0..3

Pop

Drops the last note from the melody

zplay "0 1 2 3 4", pop: true
z1 "0 1 2 3 4", store: true, pop: true # Drop the last every cycle and stops the loop

Shift

Removes first note from the melody

zplay "0 1 2 3 4", shift: true
z1 "0 1 2 3 4", store: true, shift: true # Remove the first every cycle and stops the loop

Pick

Pick notes from the melody with duplicates. The chances of getting more duplicates will be greater with long melodies. Same method as in Sonic Pi.

zplay "q 0 1 2 3 4", pick: 2
z1 "q 0 1 2 3 4", pick: 4

Stretch

Streches the notes given amount of times. Same method as in Sonic Pi.

zplay "q 0 1 2", stretch: 2 # Plays 0 0 1 1 2 2

Object transformations

Object transformations are always run after the order transformations. Ordering of the melody does not affect the result of object transformations (other that some notes might be missing after the order transformations). Object transformations are processed in order form left to right.

Augment

Intervallic augmentation will alter the melody by adding intervals to the degrees and parsing new note for that degree.

Example:

z1 "q .0 .0|q0 e1 q.2|2 e1 q2 e3|h.4|e7 7 7 4 4 4 2 2 2 0 0 0|q4 e3 q2 e1|h.0", augment: {
  1=>"3",
  2=>"#",
  3=>->(){rrand_i 1,4},
  4=>->(){rrand_i 1,2}
}

Note that augmenting is done by means of intervals, meaning 2=>1 will do nothing (1 = unison).

Harmonize

Harmonizes existing melody by creating chords from degrees using intervals, meaning 1=>1 will do nothing (1 = unison).

zplay "0 2 3 4", harmonize: 3
zplay "-3 -2 -1 0 1 2 3", harmonize: [3,5]
zplay "0 2 3 4", harmonize: [2,"#5","b4"]
zplay "0 2 3 4", harmonize: {1=>3,4=>5}
zplay "0 2 3 4", harmonize: {1=>[3,5],4=>[2,3,4]}

# Harmonize creates chords so you could also play arpeggios from that and invert those chords
zplay "G'e1 2 3' q 9 8 7 6 5 4 3 2 1 0", harmonize: [-3,-5], chord_invert: -2

Compound

Adds compound interval to the harmonization, added note is one octave up or down.

zplay "q 9 8 7 6 5 4 3 2 1 0", harmonize: 3, compound: 1
zplay "q 9 8 7 6 5 4 3 2 1 0", harmonize: -3, compound: 1

Flex

Flex will multiply or shorten the length of the melody

zplay "q 0 1 2 3"
zplay "q 0 1 2 3", flex: 1
zplay "q 0 1 2 3", flex: -0.5

Silence

Changes the note to rest from the given index (0-n)

zplay "q 0 1 2 3", silence: 2
z1 "q 0 1 2 3 4", silence: ->(i){i}

Loop transformations

Loop transformations are type of transformations that are only done in loops. These type of transformations are done before order and object transformations.

Phase

Phase will force the loop to go out of sync causing the phasing effect when multiple loops are playing.

Example:

z1 "q 0 1 2 3"
z2 "q 0 1 2 3", sync: :z1, phase: 0.1 # Sleeps 0.1 before each cycle

Pattern

Played melody or rhythm can be changed in a loop by defining a new pattern:

z1 "h K S (r K) S",
  K: :drum_heavy_kick,
  S: :drum_snare_soft,
cycle: [
  {at: 2, pattern: "h K (S K) (r K) S"}
]

Custom transformations

Create your own transformations using the define method. Order transformation method must have 2 parameters: array and loop cycle index. Object transform method must have 3 parameters: note object, loop cycle index, note index and melody length.

Example:

define :foo do |melody,loop_i|
  print "foo"
  print melody
  print loop_i
  return melody.reverse
end

define :bar do |ziff,loop_i,note_i,melody_length|
  print "bar"
  print ziff
  print loop_i
  print note_i
  print melody_length
  ziff[:note]+=5
  return ziff
end

z1 "q 0 1 2", order_transform: :foo, object_transform: :bar

Apply transformations

All transformations (and all other parameters, amp, release etc.) can be applied to notes using apply:

Apply to a single note for multiple times:

z1 "q 1 {1 5 2 0}~", synth: :rodeo, release: 0.1, apply: [
  {
    at: 1,
    release: 3.0,
    synth: :fm,
    transpose: -1,
  },
  {
    at: 1,
    with_fx: :ixi_techno,
    phase: 0.9
  }
]

Apply to range of notes. Use lambas to randomize the values:

z2 "q 1 5 2 0", synth: :pluck, apply: [
  {
    at: 3..4,
    transpose: ->(){rrand_i(-1,4)},
  }
]

Apply can be combined with run effets (which affects all notes):

z3 "q 0 ^0 3 [2,5,7] 7", scale: :minor,
  synth: :fm,
  amp: 0.5,
  cutoff: range(60,130,5).mirror,
  res: 0.9,
  release: 0.1,
  run: {with_fx: :reverb, room: ->(){rand(1.0)}},
  apply: {mod: 6, with_fx: :echo}

Clone this wiki locally