Note Names / Pitch Classes

Yes, Sc is at the same time the “orchestra” and “score” language, so it’s nice to have some “affordances” for notation…

Ps. It should be straightforwards to extend the model to allow strings for degrees, so that something like the below would be accepted:

var d = "f d b g f b' a+ e d+ c-' b' f e+ d' c' b+' c' a f g+".split($ );
Pbind('scale', Scale.minor, 'root', 11, 'degree', d, 'dur', 1 / 2).play

Here + is raised one step, - is lowered one step, ’ is raised one octave, , is lowered one octave. (+ and - because in B-minor “c” is “c♯” and “c-” is “c♮”.) Also, the raise and lower qualifiers could read the amount from a field in the event, so if one liked + could be raise a half step (quarter tone), and ++ raise a step, &etc.

1 Like

I’m not a Jedi master about implementing Patterns in sc. I just studied a little to export streams to fomus (writing the superfomus quark many years ago).

But if that path is a good one, so be it. Let’s check it out.

@rdd

Have you ever played around with “quasiquotations”? I did a little test with a hyper simplified syntax inspired by lilypond. I wonder it it’s something worth exploring, or is it too “exotic” kind of thing to do?

>>> [lily|a'4 c'8 d'2|] 
[Note A (Octave 1) (1 % 4),Note C (Octave 1) (1 % 8),Note D (Octave 1) (1 % 2)]

@smoge I think the more usual. way to do this would be “a’4 c’8 d’2”.lily, no?

in either case the return value needs to be something - for you this is a Note object - I think we should have these available rather than relying on the degree field in Event, something lives between whatever DSL and both audio and notation. Notes would have methods to convert to Events, extract freq, to or render notation etc.

So you could write something like:

a = "e'4 b2".lily.asPbind(root: \e, instrument:\sawSynth)

and also

a = "e'4 b2".lily; Notate.musicXML( a, blah blah)

This way we can write any number of DSLs like .lily and still have a consistent interface that lives in a few related classes that can be subclassed straighforwardly

Re the degree field in Event it has going for it that it is already there!. But I have a hard time with the scheme of using the tenth digit to indicate sharps and flats!

1s // 1.1
2s // 1.2
2b // 1.9

So (degree:1.1) produces the same freq as (degree: 1.9) - and (degree: 1.5) the same freq as (degree: 0)

Not sure why this bugs me but it just seems wrong! (Its also annoying to extend)

Yes, but is there such parser out there? I think not.

no not now…

but my point is that if we have a system of objects for named notes that can be a target for any number of DSLs - right now many peoples efforts target either midinotes, or XML or are meant to be extracted into fields in Pbinds - if instead they produced arrays of NoteNames or Notes or whatever, and those Objects had methods to make Events or Pseqs or MusicXML, the same DSL could be used in patterns or notation or whatever without having to create methods for all of the above…

We could also operate on the Arrays of notes and build other data structures to represent music such as the prefix trees you proposed in the other thread!

I’ll try to creep ahead with my proof of concept to see if I can demonstrate!

I’ve been thinking about trying to use lilypond’s simplified syntax, but which is also valid code to manipulate with modifiers. It can be so many things, but it’s fun to think about it and explore.

In this case, a sequence of notes is repeated but the intervals are multiplied by different scalars. A bit like the diagrams DSL for graphics.

seq = = [lily| 3:2{c'4 d'8} 5:4{e'4 f'8 fis'8 ais'8} g'4 a'8 b'4 c''4 |]
mod =  hsep (seq ^. dur)   (map (\x -> seq # scaleIntervals x) [0.25, 0.8, 1, 1.5, 2.5])
1 Like

Have you ever played around with “quasiquotations”?

Indeed, macros are nice! OverloadedStrings is nice for simple things too…

1 Like

But I have a hard time with the scheme of using the tenth digit to indicate sharps and flats!

Yes, but the math works, and if one uses the flat and sharp suffixes one never see the fractional parts…

About degrees & alterations & equivalence, it’s all context sensitive, which is why degrees are such a nice model?

3b is the same “frequency” as 2s if there are two steps between 2 and 3 (c.f. diatonic major), but not if there is only one step (c.f. diatonic minor), where 3b is “the same as” 2, and 2s is “the same as” 3.

Also, for people who are finickity about such things, it can be nice to tune intervals slightly differently depending on context.

Anyways, one can map between all these representation as one likes, I just wanted to say something nice about the existing pitch model, which is quite flexible, and can be quite concise.

1 Like

It’s actually very ingenious, and also flexible.

A few weeks ago I uploaded SPN and PitchClassSet, but removed them because I found some problems. I fixed them and made a Quark library related to this thread. It seems to work with the examples given, but needs more work. SPN and PitchClassSet are in this Quark library.

Detailed help documents are provided for each class, as well as a Notator score guide!

I would love to read your feedback! Thanks!

1 Like

Thinking further, its true that the default Event prototype’s degree and root system is sufficient to transcribe common practice music but there are shortcomings.

(root:1, degree:0) doesn’t know if it is C# or Db!

This is because the roots are expressed in semitones - if the roots instead were also expressed in degrees the system would be complete: (root: 1s, degree:1) would be C# (root: 2b, degree: 1) would be Db. Obviously this makes no difference in audio terms but is important for notation.

1 Like

Yes, you’d need to another key to say which spelling to use, perhaps called “spelling”?

It could have a sane default behaviour (i.e. answering ♭ for three in preference to ♯, ie. E♭ in preference to D♯.).

Ps. I’m not entirely sure re-specifing root in scale degrees would be a good idea?

It’d connect the “key” to the “scale”?

I.e. if you changed scale from major to minor with a root of “degree three”, you’d shift from E-major to E♭-minor, not to E-minor?

Pps. For notation there would probably need to be a whole lot of additional keys, i.e. “clef” &etc. &etc.

I’m not sure how it works with non-standard scales. My guess is that s and b were written with et12 modes in mind, and won’t work otherwise.

a = Scale.new((0..11), 24)
b = Scale.new((0..23), 24)
c = Scale.new((0,2..23), 24)
d = Scale.new((0,4..23), 24)
Pbind(\scale, a, \degree, Pseq([0, 1, 1s, 2, 2b, 1], 1), \dur, 0.25).play;
Pbind(\scale, b, \degree, Pseq([0, 1, 1s, 2, 2b, 1], 1), \dur, 0.25).play;
Pbind(\scale, c, \degree, Pseq([0, 1, 1s, 2, 2b, 1], 1), \dur, 0.25).play;
Pbind(\scale, d, \degree, Pseq([0, 1, 1s, 2, 2b, 1], 1), \dur, 0.25).play;

Yes, performDegreeToKey has an eccentricity, which you can easily edit locally.

It divides stepsPerOctave by twelve, but it’d be nicer if it divided twelve by stepsPerOctave, so:

var scl = Scale((0, 3 .. 21), 24);
[0, 0s, 1b, 1].collect { | each | each.degreeToKey(scl, 24) } == [0, 0.5, 1, 1.5]

C.f.:

https://github.com/supercollider/supercollider/blob/develop/SCClassLibrary/Common/Collections/Scale.sc#L91

and

https://github.com/supercollider/supercollider/blob/develop/SCClassLibrary/Common/Collections/SequenceableCollection.sc#L703

(It’s the same difference if stepsPerOctave is twelve…)

1 Like

This is an interesting and important discussion.
I think we should also think about chords.

For example, how could we notate Ger. 6 for major and minor?
The root of Ger. 6 should be considered from two different points of view:

  • Function: The functional root is the non-sounding tone, namely the diminished fifth below the lowest tone.
  • Step: the lower tone that forms the augmented sixth with the other tone of the chord.

However, at the moment I think the second view of the point is enough.

The following are my thoughts:

  • For musicians:
    • for minor
      [6, 8, 10, 11s] or [-2, 1, 3, 4s]
    • for major
      • [6f, 8, 10f, 11s] or [-2f, 1, 3f, 4s]
      • [6f, 8, 9s, 11s] or [-2f, 1, 2s, 4s]
    • chromatic
      [9, 13, 16, 19] or [-5, 1, 4, 7]
  • for supercollider users:
    • for minor
      [5, 7, 9, 10s] or [-3, 0, 2, 3s]
    • for major
      • [5f, 7, 9f, 10s] or [-3f, 0, 2f, 3s]
      • [5f, 7, 8s, 10s] or [-3f, 0, 1s, 3s]
    • chromatic
      [8, 12, 15, 18] or [-4, 0, 3, 6]

When building a secondary Ger. 6, which should be used? one for minor, one for major or one for chromatic?

The current convention of \root and \degree for pattern in SC is not so intuitive, I think…

Anyway, my idea of a PitchClassSet and SPN is documented and can be read online.:

To see some usages in short context:

If these links does not work, you could download the files from Notator/_Help (rendered HTML) at main · prko/Notator · GitHub

Otherwise, you can install that quark:

1 Like

I think the idea would be that the root would be in degrees relative to C (just as now it is semitones relative to C) so no spelling key would be required. (root: 1s, degree: 1s) would be C## for example.

root might also allow Symbols, so one could write: (root: \c#, degree: 3) - e#. and [3, 1, 2, 3, 5, 4, 4, 6 , 5, 5].root(\Db, 3] perhaps.

to determine additional accidentals you would have to look at the semitones in the scale degree and compare to \major - so degree 4 in Scale(\lydian) would give an alteration value of +1 for example.

I’ll have to look at this - is this not a bug?

1 Like

If not a bug, we could say it has space for improvements or fine-tuning

I would like to say something related to the topic of this thread with a slightly broader and extended perspective. It would involve some radical changes, but I am sure that this change is beneficial to make SuperCollider more accessible to newcomers and also more intuitive for existing users.

Since this summer I have been trying to get musicXML out of SuperCollider. It should of course be accompanied by the concepts of music-score-similar representation in sclang, interval, pitch and so on. However, I found some conflicts with the following existing classes in SuperCollider:

  • Score
  • Interval
  • Pitch

I had no problems with these classes before I tried to implement musicXML export from the score-like representation in SuperCollider, but now it becomes a problem.

As a teacher, I should also consider that SC newbies expect an equivalent functionality to score in SuperCollider.

So it would be nice if Score could be renamed to ScoreOSC, because then ScoreSheet or ScoreMusic could be implemented as equivalent functionality as a score for musicians.

The same concept can be applied to other class names:

Interval could be renamed to IntervalInteger or IntegerRange, because then IntervalPitch may be introduced as the equivalent of interval in music theory.

If Pitch is renamed to PitchFollower, then PitchAbs and PitchRel could be provided in conjunction with PitchClassSet. The names PitchAbs and PitchRel are the slightly varied names of the classes which suggested @semiquaver.

In Quarks, there is a Note class which represents notes in ABC notation, and a PitchClass class which performs some specific functionality internally in CTK Quarks. When adding the concepts and functionalities mentioned in this post as Quarks, there may be some duplication or inconsistencies with the Note and PitchClass classes. Actually, my PitchClassSet is renamed from PitchClass to avoid such problems. This is why I think such things should be centrally organised. At the moment I am working with the class name Notator, but it would be ideal if the developers could think together and come to an agreement.

One detail : it does seem like the Interval class is rarely used - a quick grep of the class library and Quark repo only turned up a couple of lines. I see this notation (1, 3..9) much more often…

1 Like