Ziffers - Numbered musical notation

I added the harmonization transformation. It works like this:

zplay "1 3 2 5", harmonize: 3
zplay "-3 -2 -1 0 1 2 3", harmonize: [3,5]
zplay "1 3 2 4", harmonize: [2,"#5","b4"]
zplay "1 3 2 4", harmonize: {1=>3,4=>5}
zplay "1 3 2 4", harmonize: {1=>[3,5],4=>[2,3,4]}
zplay "G'e1 2 3' 9 8 7 6 5 4 3 2 1 0", harmonize: [-3,-5], chord_invert: -2

And also changed the flat sign from & to b! (this ought to break some current ziffers melodies but i think its better in the long run).

1 Like

Just played around with harmonize - nice idea and very useful!

It wasn’t clear to me how harmonize works so referenced the code and added my own notes:

# harmonize a third over each degree
zplay "1 3 2 5", harmonize: 3

# harmonize a third and fifth over each degree
zplay "-3 -2 -1 0 1 2 3", harmonize: [3,5]

# harmonize with second, sharp 5, and flat 4 over each degree
zplay "1 3 2 4", harmonize: [2,"#5","b4"]

# harmonize with third over the second degree (1), and with fifth over the fifth degree (4)
zplay "1 3 2 4", harmonize: {1=>3,4=>5}

# harmonize with the third and fifth (major chord) over the second degree (1)
# harmonize with the second, third, and fourth over the fifth degree (4)
zplay "1 3 2 4", harmonize: {1=>[3,5],4=>[2,3,4]}

The last example I can’t quite parse, perhaps in part because I’m not understanding how the arpeggiator works:
zplay "G'e1 2 3' 9 8 7 6 5 4 3 2 1 0", harmonize: [-3,-5], chord_invert: -2

It looks like arp behaves differently depending on whether it is operating on chord numerals or scale degrees. Fair enough, but it looks arp does nothing when it encounters a scale degree:

zplay "Gq12 2"

{run: 54, time: 0.0}
 ├─ "Ziffers: G'q12' 2"
 ├─ "Ziffers: q12"
 └─ synth :beep, {release: 1.5, sleep: 1.0, pitch: 0.0, amp: 1, pan: 0, degree: 2, note: 64.0}

Only the third (2) degree is being played, the arp isn’t doing anything. Replacing with a chord:

zplay "Gq12 2"

{run: 56, time: 0.0}
 ├─ "Ziffers: Gq12 i"
 ├─ "Ziffers: q12"
 └─ synth :beep, {note: [64.0, 67.0], key: 0.0, scale: 0.0, release: 0.375, sleep: 0.25, pitch: 0.0, amp: 1, pan: 0, skip: 0.0}

Ok now I have a two-note chord being played with E and G, the third and fifth degress of C major. How did my expression result in those notes? I would expect the second (1) and third (2): D, E

Adding another degree to the arpeggiator:

zplay "Gq123 i"

{run: 58, time: 0.0}
 ├─ "Ziffers: Gq123 i"
 ├─ "Ziffers: q123"
 └─ synth :beep, {note: [64.0, 67.0, 60.0], key: 0.0, scale: 0.0, release: 0.375, sleep: 0.25, pitch: 0.0, amp: 1, pan: 0, skip: 0.0}

Now an expression of 123, which I would expect to map to the second, third, and fourth degrees of C (D, E, F) is giving: E, G, C?

I’m not depending on the arpeggiation feature, but would use it if I could understand it better.

Finally, some friendly advice - I would consider reverting or going a different direction with the zero-based scale degrees. I’m a longtime programmer too, I understand the motivations for expressing some types of ranges of degrees in a tidy mathematical sense, but it is really awkward both for writing naturally (wait do i add or subtract here) and reading later (wait, do i add or subtract here). I think being able to express ideas and patterns using same terms in one’s head leads to the best experience. When I see the numbers 1 3 5 or 5 7 2 4 together those have strong connections in my head to I and V7 chords. I feel it really hurts the readability of scripts when you have to carefully parse through and remap every number you see in your head. As well, the harmonize option isn’t consistent as it appears to use the actual degree you specify and not the zero-based degree. I think you could achieve the same kinds of use cases with another “modulo” operator or mode that would explicitly declare use of those kinds of numeric ranges for a specific ziff or part of one.

Ok, first about G:

Arpeggiator G works only with chord objects, and the numbers there are indexes 0 to n from the chord array. If chord array doesnt have that index, for example 2 it overflows to 0.

Resulted arpeggio pattern is only added to the chord objects:

zplay "G'q0 1 2' i" # {arpeggio: [0,1,2], chord:[60,64,66]}

So in the example with the arpeggio I should have been using “0 1 2” but also “1 2 3” works because the indexes overflow. Here’s revised example:

# Harmonizes degrees into chords and create arpeggio from the chord notes 
zplay "G'e0 1 q2' 9 8 7 6 5 4 3 2 1 0", harmonize: [-3,-5], chord_invert: -2

# Is same as:
zplay "Ge0e1q2 9 8 7 6 5 4 3 2 1 0", harmonize: [-3,-5], chord_invert: -2

# But '-escapes are cool because you then you can combine the chord notes
zplay "G'e0 012 1 012' 9 8 7 6 5 4 3 2 1 0", harmonize: [-3,-5], chord_invert: -2

The chord pattern in the arpeggio works because of the groups change that allows you to type chords easily:

zplay "0 036 2 246" # Grouped degrees are chords

Ok … and then about the harmonize and 0-based notation:

Harmonize uses interval numbers because that is also how I have learned about harmonization, so in that context 1 actually pretty much means “do nothing”.

I changed the notation to 0-based because i got frustrated to support two notations in transformations, like inversions etc. Weighted pro’s and con’s of both degree numbers and set theory numbers and ended up with a conclusion that 0-based degree is superior because inverse of 0 is 0 :sweat_smile:

I’ll consider adding the degree numbers back as an alternative as i also like it, but I dont see that I have time to support both notations in transformations which performs some kind of mathematical magic to the melodies.

2 Likes

Refactored and added a lot of transformations this weekend. Also added custom transformations which is a simple way to create your own. Try it out and if you make something new I would gladly include those in the library :slightly_smiling_face:

1 Like

Added option to switch back to the degree based (1-9) notation.

Also some other minor changes like triplet length chars and melodic patterns.

1 Like

Added new notation for euclidean rhythms which can be used to create drum lines or rhythmic variations to melodies.

Syntax: {on beat}<1,4>{off beat}

Also created a [ziffers channel] to toplap chat which is more suitable for more random discussion.

2 Likes

At first, I thought it was a little weird , but the more I think about this, more I think its great (weird is usually good, I like weird). This notation free your mind of thinking in a specific key. I will give it a try.

Weird is fun indeed :upside_down_face:

There’s been a lot of changes to the syntax and features … so even I cant remember all anymore. Be sure to check out the Melody, Loop, Transformations and the Enumerables from the wiki: https://github.com/amiika/ziffers/wiki

Especially custom transformations and enumerables open up some fun possibilities and can be used as a framework to test and create new generative melodies.

2 Likes

…and I’m back! :wink:

Been a while!

In the meantime (meaning, just this weekend), I “discovered” musical set theory. Had heard of it, of course, including in this thread. And I was using some concepts related to it. Particularly “pitch class”. That’s a very useful concept for a number of situations. And I was aware enough of numbered musical notations that it didn’t sound weird at all when I dove into this one. Especially since it’s immensely relevant to the way Sonic Pi does things.
Which is why I’m back.

So, a bit more background to my “discovery”.

For a while, now, I’ve had a favourite scale for noodling. I call it my “noodling scale”.

G, A♭, B, C, D♭, D, F

A large part of the reason it’s so fun is that I have it “in my fingers” when I play a sax-style windcontroller. It’s easy to play without too many cross-fingerings.
And it sounds pretty good in a number of ways. It includes the diminished scale (diminished 7th chord) so it has two tritones and four minor thirds. (It actually has a third tritone.) Quite a bit of chromaticism (4). Enough fourths/fifths (3). Sounds good on G7 and G7(♭5). As we say:

Good enough for Jazz!

Altogether, a nice scale for endless noodling.

My “problem” was that I wanted to create cool chord progressions to jam diatonically with it. To this day, I have a hard time playing on non-diatonic chord progressions. I really enjoy diatonic ones.

So… what’s a musicker to do?
Well, let’s find a way to list all the chords in that scale. Not as easy as it sounds, especially if you want to be exhaustive… and skip inversions of the same chord.

I knew it was a matter of combinatorics applied to music (stumbled upon some Wolfram Alpha pages to prove it). Yet I didn’t have the math chops to make sense of it all.

A fortuitous encounter (with a friend’s child who’s now finishing a music degree at McGill) led me to set theory.

And, yes, it’s been mostly applied to atonal stuff. Which can be very offputting, of course. Yet, there’s something there. Because our perspective on tonality ends up being constraining, in practice. And it’s biased in very particular ways.
(Disclaimer: I was trained as an ethnomusicologist.)

Maybe because I’m hungry, I’m thinking through a “meat & potatoes” analogy, here.
If you’ve only ever had beef, tasting other meats can open up a whole new world. It’s pretty obvious to most people that there’s a large variety of meat, out there. Not everyone gets to taste all of these other meats. They might not enjoy them, yet tasting those trains your palate to differences which aren’t attributed to spices or cooking methods.
Most people don’t realize how many varieties of potatoes there are in the World (around 4k, 80 of which sold in the UK). So, if you start paying attention to the flavours of diverse potatoes, you’ll expand your “taste vocabulary”.

Tonality, as we conceive of it, is pretty meaty. Volumes upon volumes have been written to theorize it. “Everything comes from the Church Modes and stacked thirds” is a summary of an obvious bias in a remarkable body of literature. And our use of 12TET in this century reduces things even more. Though meaty, tonality has become like potato purée made with Yukon Gold. :wink:
There are other ways to make potatoes and there are other varieties of potatoes. Maybe the other approaches to tonality don’t suit your tastes, at first. They’re still worth exploring.

So… Back to (musical) set theory. And numbered notation.

The basic principles are very easy to understand by someone who’s worked with SPi. Indeed, it has part of the same effect of putting the ‘A’ in “STEAM”. Understanding Set Theory through music can be part of this movement of getting the powers-that-be understand the value of music.

And, it turns out, it can actually be fun.

So, I found a Pitch Class Set calculator:
https://www.mta.ca/pc-set/calculator/pc_calculate.html

Thanks to it, I was able to learn quite a bit about my “noodling scale”. Such as the fact that it includes 4 instances of chromaticism, 3 wholetone intervals, 4 minor thirds, 3 major thirds, 4 fourths/fifths, and 3 tritones. I also found out that it includes three Viennese/Rite chords (the calculator said six, but I think it’s because it counts inversions). And a “Dream chord”, from LaMonte Young’s work.
That one is easy to find if you know to search for it. Using “traditional” approaches to tonality, I might not have given it much thought.
And, depending on voicing (which you can also notate through PC Set), it can sound pretty good.
Here’s a quick example of my noodling scale used on top of that chord:

Oh, BTW… My noodling scale is part of the 7-19A (so its complement is the 5-19B pentatonic scale). The prime form is: [0,1,2,3,6,7,9].

Which I could (and will!) use as a ring in SPi! :wink:

Then, I could (and might…) use that as part of Open Educational Resources helping learners develop their theoretical approaches to musicking.

All this to say, reviving this old thread…

There’s room for Musical Set Theory in this here Sonic Pi world.

3 Likes

Thanks for bringing this up again. I always get some boost in motivation to learn more and continue working on ziffers when similar interests collide in this forum.

For the past year or so i’v been randomly writing a new parser for Ziffers. New parser will have huge impact on how easy it is to expand and experiment with different things. Old parser was such a cumulative mess that always ended up breaking something if any changes were made. New parser is written in Treetop and biggest change will be the support for generative and recursive syntax and set operations.

Random syntax examples:

“(1,4)” # Random between 1 - 4
“((1,4),(5,9))” # Random between random and random
“((1,4),(5,[6,7,8,9]))” # Random between random and random that is very random

Set syntax examples:

“{1 2 3 4}” # Standard set
“{1 2 3 4}+1” #Add one to each. All other mathematical operations supported as well
“{: (1,4) :5}” # Random 5 times
“{ (1,4)…(5,9) }~” # Suffled set that is generated from random range between random numbers
“{1 2 3 4}+{-1 2 -3}” # Cross product
“{1 2 3 4}@+{-1 2 -3}” # Cartesian product

This new generative syntax can also be used with the Lsystem rules, which will open new possibilities to incomprehensible fractal melody generators.

On top of that there is a new way to do transformations, for examle:

use_synth :piano

a = zparse "q 0 2 1 4"

b = a.invert

c = a.retrograde

d = a.invert.retrograde

e = a.transpose -3

zplay (a*2+b*2+c*2+d*2+b+e)*2

Ziffers library will also include a lot of different experiments made in the past, including support for custom scales (via monkeypatch), markov chain generator, cellular automatons and more enumerators that create different number sequences etc. Over all there’s still so much to document that it will take some months to do it. I’ll start a new thread once its ready to be published since the syntax will also have some breaking syntax changes and there is plenty of old stuff in this thread that won’t work anymore.

If some of you want to try it before it’s fully documented it can be found from separate ziffers2 branch.

2 Likes