(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 X:1 M:8/8 K:D FFF2 FFF2 | FADE F4 ] 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 X:1 M:8/16 K:D 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:
X:1 M:8/16 K:D 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 |