For the next attempt in BetaBlocker bytecode evolution I wanted to favour patterns that had a rhythmic nature by measuring them with this function:
(defn freq [l n] (defn _ [c] (cond (>= (+ c n) (count l)) 0 (= (nth l c) (nth l (+ c n))) (+ 1 (_ (+ c 1))) :else (_ (+ c 1)))) (_ 0))
Which looks for repeating values spaced apart by “n” positions, so (freq ‘(100 1 2 3 100 4 5 6 100 7 8 9 100) 4) returns 3, as it finds 3 pairs of equal values (100) distanced by the specified 4 positions.
With this fitness function:
(+ (* 50 (count (num-unique res))) ; unique notes are very good (freq res 4) ; equal notes every 4 beats are good (freq res 6)) ; equal notes every 6 beats are good
We favour rhythmic components of 4 or 6 beats and boost the uniqueness score by multiplying it by 50. After some generations, we get a high scoring individual: 23 23 13 22 7 12 17 20 12 23 23 5 0 7 12 3
Which disassembles as:
loop:
note ; play & remove top of stack (zero when empty)
note ; play & remove top of stack
dec ; decrement top of stack
dup ; duplicate - pushes a copy of stack top
pshi 12 ; push the value pointed at by address at 12 (self read)
not ; performs bitwise not on stack top
pip 12 ; increment value at address 12
note ; play & remove top of stack
note ; play & remove top of stack
pshl 0 ; pushes this literal number (the 0 is at address 12)
pshi 12 ; push the value pointed at by 12 (self read)
jmp loop
This program creates a pattern from 4 separate sources, using all 16 bytes of code:
The result: “0 0 232 255 23 1 232 254 13 2 242 253 22 3 233 252 7 4 248 251 12 5 243 250 17 6 238 249 20 7 235 248 12 8” scores poorly for it’s rhythmic patterns, but it’s probable that this surprising local maxima was found by the early influence of the rhythmic fitness criteria on it’s ancestor populations.
This one was strange enough to warrant dialing into Betablocker DS to see how it actually sounded. Here it is in Hungarian Gypsy scale:
Leave a Reply to Spork factory | dave's blog of art and programming Cancel reply