Ziffers - Numbered musical notation

Dunno, which system uses 0-9? Zero as musical rest is used at least in chinese practice.

The 0 doesnt really matter until you start to use generative syntax, sequences etc. So it could be just a flag for those cases (eg. startFromZero). Anyway, generic or not 0 could then be ‘r’ like in lilypond.

Wheels on the bus (current syntax):

zplay "q14e44q46 8640 5310 8641 q4e44q46 8640 h5q.1e1h.4", key: :f

Would change to:

zplay "q03e33q35 753r 420r 7530 q3e33q35 753r h4q.0e0h.3", key: :f, startFromZero: true 

For me the most appealing thing is the relative exactness that allows retuning and reshifting of the melody by calculating.

Not yet, but will start on it next. I think it also need some new char to denote “sleep until sample is over”. For example: ‘b’. So it would be something like:

zplay  "b X X e XX h O O", samples: {"O"=>:drum_heavy_kick, "X"=>:drum_snare_hard}

It could be also possible to combine degrees to samples in a sequantial or simultanious fashion. Like with the chords “i 1234 iv 3422”. But in order that to work there would have to be different sleep notation for the samples … and I think that X is currently reserved for chord sleep but i havent used that much, usually i use generic parameter for all chords like chordSleep: 0.5.

EDIT: I think i found a better way to do this, and I totally forgot that there was a special note length ‘z’ for zero length. In some cases it may lead to “out of sync” if timing is not reseted afterwards, but in this case it works. The numerous sample options could also be passed via separate object so that you can set multiple options to a single character, like:

zplay " z B q M M M M", samples: {"M": :bd_tek, "B": {sample: :ambi_choir,opts:{hpf: 100, beat_stretch: 2}}}

Sample specific sleep could also be assigned to the opts for the sample_duration case that overrides the normal note length characters (q,w,e, etc.).

zplay "q 123 B B B", samples: {"B": {sample: :ambi_choir,opts:{rate: 0.2, sleep: (sample_duration :ambi_choir) }}}

Wow, that’s great. I think that using r for rest is a clever choice. I know that 0 is used in some systems but in my opinion, I think it’s important not to use numbers for things that aren’t notes, degrees, etc… 0 is confusing because some people might think that 0 is the foundation, the root note, etc… The distinction between numbers and letters is very clear and without confusion. I’m not really neutral when I think about that, but I think that using numbers in the same fashion than set-theory is a good way to find some kind of musicological standard.

I’ll try to play with the sample notation as soon as I can, to see what I can come up with. I love it so far.

zplay " z B q M M M M", samples: {"M": :bd_tek, "B": {sample: :ambi_choir,opts:{hpf: 100, beat_stretch: 2}}}

This syntax is cool, a bit tricky to approach at first, but I think that it’s just a matter of getting used to it.

1 Like

Ok, there’s a new version that can play samples with custom character assignation. Sequential and simultanious samples plays together quite nicely.


Tried to understand how set theory has anything to do with the numbered notation and was suprised that there is such a thing as musical set theory :sweat_smile:

EDIT: Had a quick read about the musical set theory and it seems to be more about chromatic scales and atonality, where as numbered notation is about tonality and use of degrees in certain scales. Am i right? Some ideas from it might be applicaple to tonal melodies as well. However, im still bending towards the 0…9 notation as it solves the problem. Created issue about it. Sadly it will break all of the written melodies, but those are quite easy to fix.

I didn’t had much time to play with Ziffers recently but things will be better in the next few days. I want to try to make at least a complete improvisation / composition using it. I tried the sample notation and it works really well. It’s also very easy to keep track of the parameters of each sample by formatting the text just a bit.

I’m now using it both as a way to sequence things in Sonic-Pi itself and to communicate with my other synthesizers by using midi. This is really the most advanced sub-language I know of in Sonic-Pi and I think that it’s possible to really go far using it. I especially love using it with a modular synthesizer, launching sequence and slowling mutating them.

Yes, it’s confusing at first but I almost forgot that there was a non-musical set theory after a while, ahah.

You’re both right and wrong. It’s not about chromaticism but the basic analytic tool is indeed the pitch-classes, a circular space of notes from C to C, but abstracted from any notion of pitch (it could be C2, C4, C7, we don’t care). It’s a very abstract way of seing music. The most useful and exciting tool there is in set-theory is maybe the pitch-class sets, the possible combinations of different pitch-classes. (Actually, it’s like an array of X pitch-classes).

You’re right about the fact that this theory was mostly used to describe, talk and compose atonal and contemporan music. But there is nothing in that theory that forces you to only care about atonal materials. Some people used this as a way to find new modal flavors, or new ways to escape their improvisational / compositional routine.

But if you look closely, some pitch-class sets are just the major / minor triad, things like that.

I think that’s cool. My suggestion was just to use 0 as a way to represent the first note of every given thing in Ziffers; maybe as an option like you were suggesting in another post. This way you can accomodate both people willing to follow some derivative of the chinese system, and people willing to use some kind of computational generative / set-theory infused notation.

EDIT: Having fun transcribing some Johnny Cash tunes right now.

Thanks for pointing these out. I think these ideas will be really useful for developing the ziffers language. I see pitch-class sets as quite similar to what sequences generate in the ziffers language. I think i will work on the sequence syntax next as well as the zero-based integer syntax. Interval vector is also a nice idea which could be used to control the generation of random sequences.

It’s easier to add the option for set-theory notation, like “Ziffers.setZeroBased true”, and it doesnt break existing melodies. However, the ‘0’ to ‘r’ isnt such a big change so im changing it as default … and actually then the calculations work nicely in both notations. When using degree based (1-9) notation 0 wont do anything.

Sounds great. It would be great to have such songs in the examples when ready. Nice thing about testing is to just listen to some examples to confirm that those still do sound the same.


… Aaand new version is out. Changed the rest character and added support for zero-based numbering as well as refactored sequence randomization syntax a bit.

Degree vs. set-theory influenced notation can be used like this:

zplay "q321r q321r e11112222 q321r"

Ziffers.setZeroBased true

zplay "q210r q210r e00001111 q210r"

zplay "0123456789TE", scale: :chromatic

Ziffers.setZeroBased false

This is soooo dope (as the young people say :slight_smile: ).

Thanks so much for sharing-- can’t wait to give it a go!


@amiika I think I’m doing something wrong; this code is outputting major chords, rather than the expected minor chords:

require “~/src/ziffers/ziffers.rb”
zplay “i iv v”, chordSleep: 1, scale: :minor, key: :c

Can you help me out?


Hi @bcgreen24

Chords are not using the scale-parameter, as one would expect. There is no in-built mechanism in Sonic Pi to create chords like chord( :i, :mixolydian) etc. Currently chords are built using the chord names as defined in the Sonic Pi help in “chord” section, or you can print out the chord names using:

print chord_names

Default chord name is major so it was playing that instead of minor. Chord names can be changed using this syntax:

zplay "i^min i^maj ii^m7+5-9"

I also added chordName as a parameter so if you reload the project you can now use:

require "~/src/ziffers/ziffers.rb"
zplay "i iv v", chordSleep: 1, chordName: :minor, key: :c 

Fantastic-- thank you so much!


Just pushed a big update to Ziffers to celebrate the one year old project and also created new wiki describing all new features (still needs improvement but its finally out. Yippee! And imaginary cake: :birthday:).

Well, what’s new? Loops, live rules, effects, transformations, list syntax and much more. There are also couple of breaking changes:

  • Degrees start from 0 and T=10, E=11.
  • Consecutive notes are parsed as chords (can be disabled using groups: false)

Probably some others as well. Just look at the examples and the wiki.

1 Like

Congratulations on your work and update! I’m mostly a community lurker and have known about Ziffers for a while and liked the idea. Just recently I started taking first steps to create some Sonic Pi scripts that will be a combination of music theory references and pop music toolkit. I’d like to start using Sonic Pi more regularly and this intersects nicely with a desire to write up a cheat sheet relating to several months of casual study. Another motivation is to have something to replace Hookpad - a tool related to the Hooktheory books I’ve been reading. I like the idea of how it works but I’m always spending way too much time fighting the interface and not getting the results I’d like. With Ziffers I should be able to get the same functionality of looping progressions, harmonizing multiple voices, drums, bass line with just a few lines of code. Plus fine grained control over timings, and using my own samples or virtual instruments. That’s great!

Thanks. Just made a small update to Ziffers that fixed a strange indentation bug and also added a new transformation: Compound intervals

Hooktheory and Hookpad looks interesting. Ill look into those … my theory knowledge comes from the “internet” meaning mostly from wikipedia, research articles and free ebooks. So its bit chaotic what comes out next :sweat_smile:

Currently researching and implementing musical transformations … meaning simple stuff like inversions and retrogrades to more complex like augmentation. Harmonizing existing melodies is actually next on my todo list.

The main idea about transformations is that you could run multiple transformation at once (processing order from left to right) and for example use cycle to change the transformation values depending on the current cycle of the loop. Transformations are the “last” thing done before the melody is played so you can also combine those with permutations and combinations. Still bit early to say how its gonna work but it seems really promising.

There’s so many interesting things to experiment with that its gonna take some time to stabilize :slight_smile:

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.

1 Like

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.

1 Like