-- Leo's gemini proxy

-- Connecting to thrig.me:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

Random Rhythm Generation


First up, some notation. The "x" in the following indicate when noise is made, and the "." indicate silence (or, sometimes, that there is an onset, but it is much quieter than those marked with an "x"). What makes the noise or how long that sustains for are not indicated.


    x...x...x...x...

The above is known as "four on the floor" (one beat every quarter note) especially if sounded with a bass drum in dance genres. A steady beat can be too boring, or might help ground things should the other parts get too wild.


The observant might notice that this is a binary sequence, which could be converted to other forms via simple transliteration.


    x...x...x...x...
    1000100010001000
    ()))()))()))()))

There are rhythmic patterns where the parentheses balance. But that's not the rabbit hole for this episode. Our steady "four on the floor" can be contrasted with one of several rhythms where the beats are much less evenly distributed.


    x...x...x...x...
    xxxx............

steady.midi

lumpy.midi


Some might notice that the lumpy rhythm repeated four times looks somewhat like the original "four on the floor", only slower and with more onsets during each abstract beat. Using the same rhythm only playing it faster or slower does see use in music, though maybe not with the sudden onset clumps.


    xxxx............xxxx............xxxx............xxxx............

Good rhythms (for humans) tend to more or less equally partition the space, just as musical scales tend to more or less equally partition a frequency doubling (octave). That is, you'll see more of


    x..x..x...x.x...
    x.xx.xx.
    x.x.x.x..

and less of


    xxxx.......x....
    xxxxx...
    xx....xx.

in the wild. One question might be how to generate rhythms that are closer to those more regular than otherwise. Another would be how to convert the rhythm notation into MIDI or some other form for listening to.


Conversion


One method would be to substitute in note names and rests for LilyPond (or some other score program) and then use LilyPond to render sheet music and MIDI.


    $ printf x..x..x..'\n' | sed 's/x/c4 /g; s/\./r4 /g'
    c4 r4 r4 c4 r4 r4 c4 r4 r4

Otherwise, there are MIDI libraries available for various languages, or you could write your own library as the protocol (as of version 1.x) is not too complicated and has many implementations. The original specification was aimed at not very expensive hardware back in the 1980s, for better or worse.


    (require :asdf)
    (asdf:load-system :smolmidi)

    (defun midi-pattern (file vector)
      (multiple-value-bind
          (track leftover)
          (smolmidi:patternize (smolmidi:new-track) vector)
        (smolmidi:write-midi-file file (list track)
                                  :footer-dtime leftover)))

    (midi-pattern "steady.midi" #16*1000100010001000)
    (midi-pattern "lumpy.midi"  #16*1111000000000000)

Generation


Random generation will likely need a filter of some sort to select for "better" rhythms, which would be those that are more evenly spaced than not. "Euclidean rhythm" is a thing. With a suitable filter one can then generate random beat patterns that contain N onsets in M beats where N is ideally less than M.


One filter method would be to score the beat pattern for how closely it matches some existing pattern. Another is to compare the distances between the onsets; evenly spaced onsets will have a lower standard deviation. The random onsets however may not line up where they might be expected musically. That is, a distance filter would consider the following rhythms equivalent.


    1000100010000100
    0100010001000010

A hybrid scoring system might check both the distances and whether the onsets line up on expected accent beats. Much of this depends on what you are looking for. It may be best to not use too many trials to find the best rhythms, as these may too closely match some existing standard pattern, e.g. four on the floor, and one does not need to waste CPU to find that.


It might be simpler to make do with known and accepted rhythms, possibly with minor variation. This uses knowledge rather than searching around. Either approach has pluses and minuses.


Some patterns are rotations of others, so a simple search may be to rotate a known good rhythm by some amount. Sometimes this will produce other known good rhythms.


    x.xx.xx.
    xx.xx.x.
    xx.x.xx.

Multiple Rhythms


A useful technique may be to generate "four on the floor", and use random (with filtering) methods to select 2, 3, 5, or 7 onsets in 16 beats (or whatever you want) in some number of other tracks using some number of other instruments. Randomizing the instruments and MIDI velocity may also turn up interesting results. The "four on the floor" helps ground the otherwise maybe too excessive randomization and changes to the randomization: a track might vary every eight measures, repeat prior patterns it has used in some sequence, etc.


beats.mp3

fast.mp3


But the code that generates these files is far too messy to share, and I've somehow nerd sniped myself into writing a Common LISP MIDI library.


/blog/2023/09/23/random-melody-generation.gmi

smolmidi - a small library for writing MIDI in Common LISP

https://metacpan.org/pod/Music::RhythmSet

-- Response ended

-- Page fetched on Wed May 22 02:29:32 2024