💾 Archived View for thrig.me › blog › 2023 › 12 › 09 › srbm.gmi captured on 2024-03-21 at 15:13:32. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-12-28)

-=-=-=-=-=-=-

Semi-Random Beat-Maker

srbm.lisp

out.mp3

For some regularity, there are onsets on beat 1, 2, 3, 4, and another four beats on the half-beat mark. These would usually be a bass drum and hi-hat, though the above code randomizes the pitch and thus drum selection, which is bad if you know what you are doing, and might be good if you're throwing stuff at a metaphorical wall to see if anything sticks. Otherwise longer rhythmic patterns are generated though not totally randomly. There is a wide range between

    1000100010001000
    1111000000000000

and one method to score such patterns is to take the standard deviation of the distance between subsequent onsets, wrapping around at the end of the beat.

    (require :asdf)
    (asdf:load-system :statslite)   ; https://thrig.me/src/statslite.git

    (defun pattern-onset-deltas (pattern)
      (let ((deltas) (len (array-dimension pattern 0)))
        (loop for i from 0 for n across pattern do
              (when (plusp n)
                (loop for j from (1+ i) do
                      (when (plusp (aref pattern (mod j len)))
                        (push (- j i) deltas)
                        (loop-finish)))))
        deltas))
    (defun pattern-score-sdev (pattern)
      (let ((stats (statslite:statslite (pattern-onset-deltas pattern))))
        (statslite:statslite-sd stats)))

    (defun score (pattern)
      (format t "~a ~a~&" pattern (pattern-score-sdev pattern)))

    (score #16*1000100010001000)
    (score #16*1001000100010000)
    (score #16*1010001000100000)
    (score #16*1100010001000000)
    (score #16*1100100010000000)
    (score #16*1101000100000000)
    (score #16*1110001000000000)
    (score #16*1110010000000000)
    (score #16*1110100000000000)
    (score #16*1111000000000000)

score.lisp

    $ sbcl --script score.lisp
    #*1000100010001000 0.0
    #*1001000100010000 0.8164966
    #*1010001000100000 1.6329932
    #*1100010001000000 2.4494898
    #*1100100010000000 2.9439204
    #*1101000100000000 3.559026
    #*1110001000000000 4.2426405
    #*1110010000000000 4.7609525
    #*1110100000000000 5.354126
    #*1111000000000000 6.0

A score of zero (no variance between the onset distances) is probably too low, and there are less computationally expensive ways to generate it. Otherwise there is a Goldilocks zone between too random and too regular, which could be reached by selecting the best (lowest score) of some number of random patterns, or selecting random patterns until the score is neither too low nor too high. Multiple such random patterns could be combined, though probably some amount of repetition should be done, as repeating yourself is typical in music. Moreso than in text. Moreso than in text. Moreso than in text. Moreso than in text.

The results are perhaps not directly usable, though could be loaded into a DAW and combined with other tracks, a suitable coda tacked on, etc.