>> Hello. Welcome back to Curlyboi Theatre, everyone. I hope you all had a lovely lunch
or time zone appropriate break. We have an exciting afternoon of more fun talks
ahead of us. So, first up, we have Tsz Tsz Kiu Pang sorry. Being a musician, Pang has composition
in his work. His most recent endeavor is using the open software, Abjad, to create
complexly notated musically. He is working to maintain software for interesting musicians.
TSZ KIU PANG: Thanks, Betsy. Hi. Sorry. Yeah, so,
today I'm going to talk about how to compose algorithmic music with Python and Abjad.
I would like to acknowledge the traditional owner of the land which I'm currently on,
so the [Indiscernible] people and also the [Indiscernible] of the [Indiscernible] nation.
I would like to acknowledge that they are the traditional owners of the land,
which I'm on and I acknowledge the elders, past, present and emerging.
Yeah. Cool. Sorry. Sorry. Who am I? I'm Tsz. And I have [Indiscernible] in my first name.
So, I work as a DSP software engineer and when I'm not working, I usually compose music and
I perform music sometimes, as well. These are my socials if you want to look for me online.
All right. So, in today's talk, I would first, you know, give some sort of background information to
algorithmic composition, just a couple examples and then we'll look into LilyPond, which is a
music engraving software, then we'll be looking at Abjad just a little bit more in detail,
including how to extend Abjad, as well. Then, I will talk about how to structure
your composition as a Python package, at least like the way that I do it, the way that I have
been doing it. And, yeah, that's it. All right. Cool. So, the best way
to introduce algorithmic composition is to give a couple of examples. So,
algorithmic composition is actually a thing that has been there for a pretty long time, you know,
much longer than computer was here. So, even in time, back in the 18th century, I think,
there was a pretty famous dice game. So, the dice game go like this...so,
you can probably see the figures on the slide. So, the top picture, like we have kind of a magic
square looking squares and music that Mozart has composed. So, the performer or another composer,
the procedure would be is something like this. They would have to roll two dice and use the
sum to look up a measure number. So, think of measure number as an index to a Python list.
So, basically, you know, using the sum to look up a measure number and then they would repeat
the process for however many times it's required and finally concatenating a new piece of music.
So, the general idea is kind of like to scramble the music by, you know, random chance. So,
you can see how, like, you know, there is a system and different procedure to this composition or
to this dice game. And it is very much doable by computer, but obviously, like, people didn't do it
by computer. I imagine I don't really know, but I imagine they were doing it by paper and pen. So,
yeah. So that was one example. In the early 20th century, we have serialism, which is, you know,
a new school of floats in music composition and one of the really prominent techniques,
in serialism, is the [Indiscernible] technique and I'm really simplifying things here.
So, we have a turn row. So, this is kind of, like, the basic idea of the technique, which is
based on a turn row, which is a series of nine repetitive pitches. Apologies for those who do
not read music. You can see the 12 different notes on the slide there. So, they are nonrepetitive in
a series and the composer can apply operations on a turn row to generate music materials
and transposition, inflection and retrograde. And the composers would apply these operation,
any of these operations to generate music materials for their composition.
So, we're looking to transposition first, we have the original turn row. I am labeling each page by
a unique page class number, which is ranging from zero to 11 because we're dealing with
[Indiscernible] technique. In western classical music, in western music, in general, it is very
much based on, you know, [Indiscernible] like in an octave, zero to 11. So, yeah.
With transposition, we're pretty much preserving the row and moving it up or down
and moving the turn row up by a turn, so, by a little bit up. And, the operation that we apply
to the original turn row can actually be done by just one line of Python code, so you can like,
you know, on my scene here, we have pitch, plus two, 4 pitch in original turn row. So,
that's, you know, that's the Python code that we have to perform to transpose. Pretty simple.
It is very much doable by a computer. Of course, a lot of composer have been doing it by hand,
which is fine, as well. But, you know, I just would like to point out, well, you know, there are
actually a lot of techniques in music composition that can be done by a computer algorithmically.
All right. So, next up, we have inversion. We're presenting a contour,
but we are flipping it upside down. So, again, this is very much doable
by just one line of Python code, you know, just a list comprehension kind of thing.
And we have five speech, 5 is a magic number in here. Of course, if you want to, you know, change
5 into 6 or 7, like, that is perfectly fine, as well. It will just be, you know, transposed,
like, up or down. So, like, moving up or down. And then we the inverted turn row below. So, you know,
that's how we generate the inverted turn row. Next up, we have retrograde. So at this time,
we're preserving a contour. So instead of having it upside down, this time, we're having it,
you know, so we're flipping it sideways and again, just one line of Python code and we are
using the reversed method in Python to reverse the lists and the rest, you know, plus two is just to
move it up by a whole tone, basically. Then we have the reverse turn row. So,
you can see, like, all these techniques, although they were invented,
like, in the early 20th century, but a lot of those, like, can actually been
done by computer. Like, you know, using today's technology, especially in Python.
All right. So, yeah. As I've mentioned, those were just a couple of examples of algorithmic
composition. There are a lot of other techniques, as well, so, there are some software which there
are also some software which help composes to compose music. With notation software,
we have, you know, Sibelius. They're rely good at doing their job, which is to notate music. We have
OpenMusic and Bach. They can use the music to generate music material kind of algorithmically,
but to notate the actual music, like the composer would often have to resort to using other
softwares and kind of similarity for notation software, as well,
a lot of the software doesn't actually provide algorithmically composition capability
to the composer so they would have to resort to using, you know, other software or composing by
hand first to get the idea of what they want in their [Indiscernible] and use the software.
So, you know, that's why Abjad kind of becomes really handy, because it
kind of bridges the gap between the notation software and the composition software. So,
pretty much like everything can be done within Abjad. So, both composition and notation.
So, to get a better understanding of where Abjad sits in this kind of software landscape,
we would have to look at LilyPond first. So, LilyPond is a music engraving program.
So, it is not in terms of the interface, it's not too different from Lapec.
The architecture is obviously very different. Here's a block diagram. So, it takes a plain text
file, a .ly file as the input and it can format files. So, like, you know,
the ly file looks like this. You can see, c4 and then we have four notes here. That's kind of
the idea of LilyPond. So, just taking plain text, generating music notation.
All right. So, I thought I would, you know, give you a really brief look at, like
of what a LilyPond file would look like. So, this is an example from the LilyPond documentation.
So, again, like, we have notes here. It notes there, just kind of like a circle, like, you know,
[Indiscernible] and, you know, those are musical notes. And, yeah, so it corresponds. We have d4,
ac and we can also see the number, which indicates the duration of each note.
Then, you can also see, like, there are features. These vertical lines, which are, you know,
corresponds to the line here and we also have some key symmetries in here, as well. All those things
you would have to specify in the LilyPond file and it can generate all these features in the score.
This is another example. You can see, like, you know, even with this thing here,
again, you can specify, in the LilyPond, and that will generate yeah [Indiscernible] in the score.
All right. And you can also do some, you know, a little bit more complicated rhythmics in the
music. You can use tuplet to group three notes inside the space of two. Three divided by two
and so on. This is just like couple of examples of, like, what a LilyPond file would look like.
All right. So, you know, those examples, they are pretty simple. You know, they are not
too many notes. Not too complicated rhythmic stuff going on and the file relatively small,
just a few lines. But you can probably imagine, like, if I'm composing a really big piece, the
file would be pretty large so this is kind of the next slide. So, this file is just really large.
You know, it's so many lines and apologies for the font. It's just really small. I'm trying to fit
in as much as possible on just one slide. And that was only about one tenth of the file that was used
to create this. So, this is my composition. And this and this. So, like, not too much music here.
I believe there are only 21 bars of music in here. And, like, it takes a really large file
a really large .ly file to generate all these. So, like, if I'm kind of, like, engraving music,
that's kind of fine. I know which note knows goes where exactly and I know how to take those things.
I have to do [Indiscernible] type the notes into the .ly file and that'll compose for me.
When it comes to composing, I often have to go back and change things in my score and if I'm
working with such a big file, a big, you know, .ly file, and I would have to look for, okay, where do
I want to change my score? Which note do I have to change? It's just like, kind of complicated
when I'm dealing with the music, note by note. So, here is where Abjad comes in pretty handy.
So, Abjad is a Python Package that helps compose complex pieces of music notation in iterative
and incremental ways and Abjad extends the Python language. So, as a composer, I can use Abjad and
utilize the power of the Python language and also other Python packages to assist my composition,
as well. And finally, Abjad wraps the LilyPond notation software, which is demonstrated by
this diagram here. So, we can create a table an instance of Abjad voice, just a Python class,
so, Abjad and voice and we have a music notation. It looks like LilyPond code, but it's not really.
And Abjad can understand that. It interprets that and it can spit out LilyPond code when you call
"Abjad.LilyPond." So you can call LilyPond to compile the code for you and that will generate a
music notation and even better, Abjad actually has the capability to call LilyPond within itself, so,
all you have to do is to create a table an instance of Abjad.voice and that
will call LilyPond instead of Abjad and generate a PDF
as the output. You don't have to look at the LilyPond code at all. Bypassing the process.
All right. So, to get, you know, a little bit more taste of, like, how to use Abjad,
I guess we'll start with a pretty simple example. So, we'll start with just four notes. So,
on my slides, here, we have of course, if we want to use Abjad, we have to import Abjad.
So, I have a list of pitches, from 0 to 11. I can actually extend it to negative number and beyond
11, as well, but I'm not going to go into [Indiscernible]. So, what I'm doing here is to
create a table an instance of Abjad.duration. So, 1/16, that would be a 16th note.
And for those of you who don't understand music, that's fine, as well. So, 1/16th is just basically
a musical note with a pretty short duration so 1/16th of a bar, I think?
Then we can use Abjad.leafmaker and provide it with the pitches and the durations and
that will generate the musical notes for us. So, the output of this piece of code kind of
looks like this. You know, just, like, four notes. So, you know, pretty simple, right?
One almost suspects, well, why do I have to do it in Abjad when I can just do it in LilyPond
with probably fewer lines of code? But here's the magic of Abjad. So, you can utilize the Python
programming language, for example, I'm using some list operation. Just like extending my pitches
list by using a list comprehension kind of thing, so I am extending my existing pitches using a full
loop. This creates a list of [Indiscernible] 16th, I think and then I'm doing exactly the same thing.
Abjad.duration, 1/16 and using the leaf maker. Leafs mean the musical notes sorry, the black
dotted notes. So, the result kind of looks like this. This is just me using a full loop in Python.
So, yeah. You know, you can only see how I can extend this technique even a little bit more.
So, we can even retrograde the Melody by the list. After extending the list, I'm extending
the list and used reversed method. So, here I am utilizing one of the techniques, but, you know,
nothing stopped me from retrograding the Melody. So, the result kind of looks like this. So, wow,
like, we can really see the benefit of using Abjad because, like, if I do it in LilyPond, like,
it would probably take me, like, quite a while to figure out, like, how to retrograde everything.
And we can also play around a bit with rhythm. So, specifying, like, 1/16th, I am using a list
of three different durations, 2/16, 4/16. You might ask, well, okay, what happens now? Because,
like, the length of the duration of the list and the length of the pitches list are different so
I believe the pitches is of length 32, I think, and durations is only of length 3. So, huh.
[Indiscernible] not work but, you know, it will actually still work. So, Abjad kind of you know,
it will cycle through the list and Evan though the two lists are of different length, Abjad
will cycle through the list so the result kind of looks like this.
And now we are doing some, like, complicated rhythmic stuff.
And for those of you who reads music, you probably noticed that, oh, there's something wrong with the
music. If you don't read music, that's fine, as well. In this bar line and so, like, there's quite
a bit of space between this bar line and this note over here. So, that's something wrong with
the music because I am playing too much with the rhythm so I would have to fix this problem
and this is actually pretty easy to fix in Abjad. So, I can, you know, specify the meter apologies,
it's musical time for those of you who don't read music. But, yeah, in essence,
I'm just, like, trying to demonstrate, all right, there are, like, a lot of useful
methods and classes in Abjad, here, I am using Abjad. You can use, this is kind of
like almost like really Pythonic kind of syntax. So, yeah. And then I'm just using the meter class,
class method, rewrite meter and that will rewrite the music for me, according to this meter.
So what I'm trying to do is fix the duration problem which occurred in the previous slides.
So, yeah. Then we have fixed the duration problem and we have a proper piece of notated music and,
you know, I have been doing this, step by step, and hopefully it's not too complicated but you
can already see how Abjad provides a really convenient interface for composer to compose
music, step by step. I can also add other stuff to the music as well. I'm going to add accents.
I'm using a full loop. It provides some iterate functions for us to iterate over the music. So,
a lot of things are really object oriented. I'm treating every note as an object.
Here, I am iterating over the music and please do not worry too much about the logical ties, it's
more like an [Indiscernible] in there, but essentially, I'm I am iterating over the
music and adding accent for every three notes, if you want, or every three [Indiscernible].
All right. So, I'm using the attach function to attach something to the music. So, you can
probably see, like, I'm adding accent. By accent, I mean this triangular looking thing to the music.
This is really iterative. So, you know, I am doing things, like, you know, step by step and I'm,
like, complicating the music. You know, just by a few lines of code every time.
All right. So, as you can see, the core object library provides many useful classes and methods,
but they are not really enough to cover algorithmic composition and techniques. So,
current extension includes object, which is the [Indiscernible] extension and the Abjad makers.
So I'm not going to talk about it because I don't know much about it. I'm going to talk about Nauert
because I am using it. It is the extension. It is based on [Indiscernible]. And it quantizes
time based events into music notation. It looks something like this. The composer would have to
provide a list of duration and pitches and that will be the input to the quantizer. It is very
much configurable and generate music notation. So, to use the package, it would be something
like this. So, pretty much similar to the block diagram, which I've just shown. So
creating a sequence, which is just a sequence that the package can understand, by providing a
list of durations and pitches and calling it with the SD input and that will do something like this.
You will be like, wow, and I really should have mentioned the durations are in millisecond. So,
yeah. One doesn't even have to understand that much about music notation and they can, you know,
write something that is as complicated as this.
So, this is pretty useful, especially for, you know, a top down approach for composition.
All right. And of course, we can utilize other Python package. So, as you can see, I'm using
NumPy here. I'm defining a function using NumPy to generate just a list of exponential distributed
durations and using NumPy again to select a you know, just a list of random
pitches for me. And finally, using the quantizer to quantize the events for us.
Now we can create music in a rather abstract way. By specifying the music duration or the total
duration of that piece and the average duration of each note, we've, you know, in seconds, then,
you know, finally, providing with a pitch set so just a list of pitches and we can have something
like this and we can also increase the density by decreasing the average duration of each note
and now we have something like this, even more complicated and now we are torturing the musician.
By changing one number, we can have so many different music generated for us. So,
yeah. I've shown you, you know, how to use the Abjad and how to use the extension,
as well. But when it comes to composing a really large piece, we can do it in,
you know, in the Pythonic way, as well. We can structure it as a Python package,
which is something that is a lot of us are doing. So you can see, like, we have README, just like a
regular repository. As you can see, we have info and set up the [Indiscernible] which indicates we
can pypi and store this, if we want to. So, I'm going into the 47 40_directory.
I can install them if I want to. The score will be built in the builds directory and where I define,
you know, each [Indiscernible] of my music and finally, we can actually py test to see everything
is working fine. This is my definition.py. So, you can see, because I am treating this as a Python
package, so I can actually import 47 from within the directory, which is not part of the Python
package, but because I'm installing other parts of the 47, as a package, so I can import 47 here
and I can use, you know, some of the modules from within the [Indiscernible] directory.
So, yeah, that was more, or less, about, all I can talk about in a half an hour.
If you want to learn more about Abjad, here is the Abjad website and the quantizer documentation.
There are also other music examples, as well, in these few links. A lot of them, they have
the link to the repository, as well. So, if you want, you can have a look at their code. So,
yeah. That's it. Thank you very much for for your time and, yeah,
I hope you will have a great day after this. >> Thank you so much Tsz, for that really,
really lovely talk. I was saying, in the chat, that I don't have a whole lot of music experience,
but I was able to follow that, thanks to your lovely explanations and it was really interesting.
We don't have any time for questions, unfortunately.
Tsz, do you have some time to step into the text chat to answer because
there were a couple of questions entered in? TSZ KIU PANG: Yeah. Definitely. I will jump
into the text chat, just in a moment. >> The Curlyboi Theatre chat,
in Venueless, I will copy the questions over there, everyone. Thank you so much,
Tsz, for a lovely talk. I know there were a lot of other music y and not music y people in the chat
enjoying it, as well. So, thank you a lot. TSZ KIU PANG: Thank you very much, Betsy.