hwechtla-tl: Studies in random generation of melodies


Mikä on WikiWiki?
koko wiki (etsi)
viime muutokset

(nettipäiväkirja 29.10.2019) Thought I'd start playing with sound programming again. It's because I gave my daughter an assignment to play me a tune, "one that neither ends nor loops". Turns out it's not too easy to do without any kind of programming skill :) And like a good kid, my daughter produced a scratch program playing random notes on a pretty weird distribution.

But I'm also interested in music generation, and I had this grandiose vision of a generator of self-similar, fractal tunes or songs, with random "transformations" thrown in at different scales. And I decided it could be worthwhile to actually implement. (It's very different from the learning approach employed e.g. here: https://www.youtube.com/watch?v=UWxfnNXlVy8)

Last time I did sound programming (tee se itse -äänisynteesi), I was dealing with the waveform structure of sound, which I often call the "texture" of sound. This time I wasn't interested in the texture - I wanted to deal directly with melodies, the structural-conceptual nature of music which has been the primary object of humankind's interest in music since the beginning of any kind of written music notation.

Then my first problem is: what's the most effortless way of making a program output notes which I can actually listen to? I wanted a format of notes that is extremely simple to produce, but programs to turn it into real sound also exist. This took me back to ABC notation (see musiikkinotaatio). True enough, it's simple to use:

atehwa@manyuk:~$ sudo apt install abcmidi timidity
[... a lot of cut lines ...]
atehwa@manyuk:~$ cat tmp/test.abc 
atehwa@manyuk:~$ abc2midi tmp/test.abc
4.02 February 22 2017 abc2midi
writing MIDI file tmp/test1.mid
atehwa@manyuk:~$ timidity tmp/test1.mid 
Requested buffer size 32768, fragment size 8192
ALSA pcm 'default' set buffer size 32768, period size 8192 bytes
Playing tmp/test1.mid
MIDI file: tmp/test1.mid
Format: 0  Tracks: 1  Divisions: 480
Text: note track
Playing time: ~7 seconds
Notes cut: 0
Notes lost totally: 0
[... listening to Jingle bells on my loudspeakers :) ]

So now we have a way to play ABC. Then let's get on with the generation! Internally I'm going to represent a "melody" as a list of time intervals, which might contain a starting note, or be empty. And notes... are numbers, raising at halftone intervals from 0 (the base note). So the above melody would be something like:

4, 4, 4, nil, 4, 4, 4, nil, 4, 7, 0, 2, 4, nil, nil, nil

Time to get rolling with this! The stuff I wrote can be seen at: https://github.com/pkalliok/random-music/blob/master/render.py

atehwa@manyuk:~/proj/random-music$ python3
Python 3.6.8 (default, Oct  7 2019, 12:59:55)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import render
>>> render.render_tune([4,4,4,None,4,4,4,None,4,7,0,2,4,None,None,None])
'f f f2 f f f2 | f a d e f4 |'

Now, time to get on with generation. [ a couple of hours of intensive coding pass ] Wow, this is so cool. I can do things like this:

>>> print(render.render_tune(generate.extend(3, 7, [0])))
d =c' =C =f a d'' d g' | A g =C, =F B e' E a | d =c' =C =f a d'' d g' | A g =C, =F E e' E a |
 e' d'' d g' b' e''' e' a'' | b a' D g c' f'' f b' | a g' G =c' e' a'' a d'' | e d' G, =c B b' B e' |
 G =f =F, ^A d g' G =c' | D =c =F,, ^A, E a A, d | G =f =F, ^A d g' G =c' | D =c =F,, ^A, A, a A, d |
 a g' G =c' e' a'' a d'' | e d' G, =c f b' B e' | d =c' =C =f a d'' d g' | A g =C, =F E e' E a |

The ready-to-use generator is in Github (https://github.com/pkalliok/random-music). You can generate different kinds of music by preseeding with the initial tune (to be extended). Sometimes the generator has quite weird ideas.

atehwa@manyuk:~/proj/random-music$ rm random.abc && make play-random
python3 make_tune.py | tee random.abc
d2 g2 d2 g2 | d8 | =C2 =F2 =C4 | z4 =C2 =F2 |
 d2 g2 d2 g2 | d8 | ^A,2 ^D2 ^A,4 | z4 ^A,2 ^D2 |
 z2 =C6 | g2 d2 g2 d2 | =F2 =C6 | z2 =C2 =F2 d2 |
 g2 d2 g2 d2 | z6 ^A,2 | =F2 =C6 | z3 =C =F2 e2 |
 G2 =c2 G2 =c2 | G8 | =F,2 ^A,2 =F,4 | z4 =F,2 ^A,2 |
 G2 =c2 G2 =c2 | G8 | ^D,2 ^G,2 ^D,4 | z4 ^D,2 ^G,2 |
 z2 =F,6 | =c2 G2 =c2 G2 | ^A,2 =F,6 | z2 =F,2 ^A,2 G2 |
 z G2 =c2 G3 | z5 ^C,2 =F, | z =C,7 | z2 =C, =F,2 E2 =c |

Or this concerto-like thing:

d2 =F2 =C2 ^G, ^C, | d2 =F2 G,2 =C,2 | =F2 A2 =F2 A2 | d2 =F2 G,2 =C,2 | 
 d2 =F2 =C2 ^G, ^C, | A2 A2 G,2 =C,2 | =F2 A2 =F2 A2 | d2 =F2 G,2 =C,2 | 
 z =F2 =C2 ^G, ^C, G | z ^A,2 =F,2 ^C, F,, d | =F2 A2 =F2 A2 | d2 =F2 G,2 =C,2 | 
 d2 =F2 G,2 =C,2 | =F2 A2 =F2 A2 | z ^A,2 =F,2 ^C, F,, d | z =F2 =C2 ^G, ^C, G | 
 d2 =F2 =C2 ^G, ^C, | d3 =c G,2 =C,2 | =F2 A2 =F2 A2 | d2 =F2 G,2 =C,2 | 
 d2 =F2 e2 G2 | A2 A2 G,2 =C,2 | =F2 A2 =F2 A2 | d2 =F2 G,2 =C,2 | 
 z ^A, ^D, A2 =C2 G, | z ^D, ^G,, e G2 B2 | G2 B2 e2 G2 | A,2 D,3 G2 D | 
 d2 =F2 G,2 =C,2 | =F2 A2 =F2 A2 | z ^A,2 =F,2 ^C, F,, d | z =F2 =C2 ^G, ^C, G | 
 =c2 G2 ^G, ^C, a2 | =F2 =C =c2 e2 =c | z e2 D2 G,2 a | z =c3 d2 A E | 
 z A,2 b2 d2 d | z f2 d2 f3 | ^A, ^D, b2 G2 D2 | =F ^A, e2 ^D ^G, d2 | 
 D2 G,2 a2 =c2 | =c2 e2 =c2 e2 | D2 G,2 e2 e2 | b2 d2 a2 =c2 | 
 D2 G,2 a2 =c2 | =c2 e2 =c2 e2 | D2 G,2 a3 g | G2 ^D ^G, a2 =c2 | 
 z ^D ^G, d2 =c2 G | z ^G, ^C, a2 =F2 =C | z =f2 d' d'2 =f2 | G2 =C2 d'2 =f2 | 
 D2 G,2 a2 =c2 | =c2 e2 =c2 e2 | z ^G, ^C, a2 =F2 =C | z ^D ^G, d2 =c2 G | 
 D2 G,2 a2 =c2 | =c2 e2 =c2 e2 | D2 G,2 e2 e2 | G2 ^D ^G, a2 =c2 | 
 D2 G,2 a2 =c2 | =c2 e2 =c2 e2 | D2 G,2 a2 =c2 | G2 ^D ^G, a2 =c2 | 

But some things sound kinda conventional:

d2 B,2 e2 e2 | d2 B,2 e2 e2 | A2 F,2 B2 B2 | B2 B2 A2 F,2 |
 d2 B,2 e2 e2 | d2 B,2 e2 e2 | A2 F,2 A2 A2 | B2 B2 A2 F,2 |
 d2 F2 e2 e2 | d2 B,2 e2 e2 | A2 F,2 B2 B2 | B2 B2 A2 F,2 |
 d2 B,2 e2 e2 | d2 B,2 e2 e2 | A2 F,2 A2 A2 | B2 B2 A2 F,2 |
 G2 E,2 =c2 A,2 | G2 G2 A2 A2 | d'2 B2 G2 E,2 | d2 d2 g2 E2 |
 =C2 A,,2 =F2 D,2 | D2 D2 D2 D2 | z A,,2 =F2 D,2 D | z D2 D2 D2 =C |

kommentoi (viimeksi muutettu 29.01.2020 21:22)