Transcription of a Short Piece for Keyboard Instrument

Hello!

There might be diverse ways of transcribing a score, and it would be great learning materials if the various codes of transcribing an identical piece are collected.

Therefore, I would like to ask you uploading your code draft which is a transcription of the Gavotte from French Suite No. 5 of J. S. Bach. This piece includes multiple voices, a tied note over a barline, rests, repeats etc. I think transcribing only first part would be enough!

Using the default SynthDef might shorten the length of the code block, but using it or not is the freedom of the contributors.

I do not set the category of this topic. It could belong to Questions or Resources according to the responses of the forum users.

This idea has arisen in the discussion at https://github.com/supercollider/learn/issues/9#issuecomment-426650608.
What do you think about our thought?
(I will write my code later. My code would be similar to Example 1 of the GitHub link above.)

I probably could tweak it a bit for musicality but anyway… using the Panola quark from https://github.com/shimpe/panola

(
s.waitForBoot({
   var soprano = Panola.new(
    ["(b5_4\\tempo[150]\\pdur[0.7] g",
        "d e_8 f# g_4 e",
        "b4_2 e5_4 c",
        "a4 b_8 c5 d b4 c5 a4",
        "c5 b4 a g b5_4 g",
        "e_4 e_8 f# g_4 e",
        "c# d_8 e f# d g e",
        "f# d a_4 g_8 f# e f#",
        "d_2)*2"
].join(" "));
var alto = Panola.new(
    ["(d4_4\\tempo[150]\\pdur[0.4] b3",
        "a_2 b_4 g",
        "f#_2 g_4 a",
        "f# r a r",
        "g r d4 b3",
        "c#4 c#_8 d e_4 c#",
        "a3_1*5/4 d4_2 c#_4",
        "d_2)*2"
].join(" "));
var bariton = Panola.new(
    ["(g2_4\\tempo[150]\\pdur[0.4] g3",
        "f# f#2 e e3",
        "d d2 c c3",
        "d a2 f# d",
        "g d g1_8 d2 e f#",
        "g a g f# e d e f#",
        "g a b c#3 d_4 c#",
        "d f#2_8 g a_4 a1_4",
        "d2_2)*2"
].join(" "));

Ppar([soprano.asPbind, alto.asPbind, bariton.asPbind]).play;

});
)

Thank you for your code block!

Panola is musician-friendly and intuitive. Gradual tempo change and dynamic change such as ritardando, crescendo etc. of Panola are perfect!

In contrast to it, my method is too complicated.

When playing, a keyboard player reads all vertical notes in the first moment in the first bar and reads the next vertical moment, and reads a score in this way until the end of a piece.

However, you wrote the score with three parts which are used variables soprano, alto and bariton.

Your code block is perfect when transcribing. However, if I imagine composing directly in SC, it seems to be not easy for me.

What do you think about writing all voices together? I tried this by using <>, but it has some problems which are described after the code block:

(
s.waitForBoot({
	
	var bwv816_4 = Panola(
		[
			"(
<b5_4\\tempo[150]\\pdur[0.7] d5 g3>
<g5 b4 g4>

<d5_4 a4 f#>
<e5_8 f#3> f#5
<g5_4 b4 e3>
<e5 g4 e4>

<b4 f# d> d3
<e5 g4 c3>
<c5 a4 c4>

<a f# d>
<b_8 a3> c5
<d5 a4 f#3> b4
<c5 d3> a4

<c5 g4 g3> b4
<a d3> g4
<b5_ d5 g2> d3
<g5 b4 e3> f#

<e5 c# g3> a
<e5 c# g3> <f#5 d f#3>
<g5 e e3> d
<e5 c# e3> f#

<c#5 a4 g3> a
<d5 b3> <e5 c#4>
<f#5 d4> d5
<g5 c#4> e5

<f#5 d4> d5
<a5 d f#3> g
<g5 a3> f#5
<e5 c# a2> f#5
<d5_2 d3>
) * 2"		
	].join(" "));
	
	Ppar([bwv816_4.asPbind]).play;
});
)

As you see, there are problems of note values: I could not find how to let each pitch in a chord sounds with different values. The following code block is the same as above, but I commented if a pitch or two pitches in a chord must have different value. The a4 in bar 6-7 would be very interesting in this regards.

(
s.waitForBoot({
	
var bwv816_4 = Panola([
"(",
"<b5_4\\tempo[150]\\pdur[0.7] d5 g3>
<g5 b4 g4>

<d5_4 a4 f#>", // Is it possible to play only a4 as a half note?
"<e5_8 f#3> f#5", // Is it possible to play only f#3 as a quarter note?
"<g5_4 b4 e3>
<e5 g4 e4>

<b4 f# d> d3", // Is it possible to play b4 and f# as a half note?
"<e5 g4 c3>
<c5 a4 c4>

<a f# d>
<b_8 a3> c5", // Is it possible to play a3 as a quarter note?
"<d5 a4 f#3> b4", // Is it possible to play a4 and f#3 as a quarter note?
"<c5 d3> a4", // Is it possible to play d3 as a quarter note?
		
"<c5 g4 g3> b4", // Is it possible to play g4 and g3 as a quarter note? 
"<a d3> g4", // Is it possible to play d3 as a quarter note?
"<b5_ d5 g2> d3", // Is it possible to play b5 and d5 as a quarter note?
"<g5 b4 e3> f#", // Is it possible to play g5 and b4 as a quarter note?
		
"<e5 c# g3> a", // Is it possible to play e5 and c# as a quarter note? 
"<e5 c# g3> <f#5 d f#3>
<g5 e e3> d", // Is it possible to play g5 and e as a quarter note?
"<e5 c# e3> f#", //Is it possible to play e5 and c# as a quarter note?
		
"<c#5 a4 g3> a", //Is it possible to play a4 for five beats and c#5 as a quarter note? 
"<d5 b3> <e5 c#4>
<f#5 d4> d5", //Is it possible to play d4 as a quarter note?
"<g5 c#4> e5", //Is it possible to play c#4 as a quarter note?
		
"<f#5 d4> d5", //Is it possible to play d4 as a quarter note?
"<a5 d f#3> g", //Is it possible to play a5 as a quarter note and d as a half note?
"<g5 a3> f#5", //Is it possible to play a3 as a quarter note?
"<e5 c# a2> f#5", //Is it possible to play c# and a2 as a quarter note?
"<d5_2 d3>",
") * 2"
].join(" "));
		
Ppar([bwv816_4.asPbind]).play;
});
)

For me, writing all voice together is easier to think and work. This would also be easy for readers or conductors. In other terms, this is a score which can be easily read by a single performer.

However, Your code block in the previous post must be used if a chord cannot have different note value.

Could you suggest a solution?

Hi prko,

The way the system is designed enforces that chords have the same rhythmic value for all notes in the chord.

Maybe it’s interesting to note that in polyphonic music, pianists tend to practice voices separately before putting everything together (because in that style of music each melody has to stand on its own, as independent from the other melodies as possible). Polyphonic music is thought of as being written more “horizontally” than “vertically”: the harmony is considered a side-effect of independent melodies playing together (unlike other music styles where chords can be considered the basis on top of which melodies are played).

For ease of reading: pianists typically read two to three lines of music simultaneously, whereas conductors somehow manage to read even many more in choral and orchestral scores. But that’s easier when it’s visually aligned on music paper than when it 's written in text format of course.

As for composing: when writing polyphonic music one typically uses techniques from “counterpoint” which also treats every line on its own and systematically constructs a second/third/etc line based on a first line (the “cantus firmus”). Again it’s easier when you see the notes visually on a staff than when you see it written down in some text format. Personally I don’t think I’d compose such music in supercollider directly (except by algorithmic composition).

So what you ask is not possible with Panola at this moment, but I don’t really see it as a limitation of the system, and in fact I’m afraid it’d open a can of worms:

Consider the following:

"<b_8 a3> c5", // Is it possible to play a3 as a quarter note?

Suppose a3 can play as a quarter note whereas b is an eighth note. At which time should c5 play then? When the complete chord is finished? Or when the shortest note in the chord is finished? …

Just to be clear: with “polyphonic music” I mean “polyphony” (https://en.wikipedia.org/wiki/Polyphony) which is a specific style of music.

Hi shiihs,

Thank you for your quick response.

I completely agree with your opinion. Your explanation and observation on the way of playing and reading are much better than mine in my previous post.

To your question at the end of your post:

Consider the following:

"<b_8 a3> c5", // Is it possible to play a3 as a quarter note?

Suppose a3 can play as a quarter note whereas b is an eighth note. At which time should c5 play then? When the complete chord is finished? Or when the shortest note in the chord is finished? …

Could we resolve it by using syntax? For example, whatever comes after the symbol ‘<’ is the value for the next chord/note.
e.g.:

"<b_8 a3_2> c5",

The code above means that c5 is played when the b_8 is finished.

"<a3_2 b_8> c5",

The code above means c5 is played when then a3_2 is finished.

Otherwise, we can also put a symbol for example !. e.g.:

"<a3_2! b_8> c5",
"<b_8 a3_2!> c5",

The two codes above means that c5 is played when a3_2 is finished.

There would be other better solutions and I think the problem you have mentioned could be resolved.
What do you think about it?

I have one more question.

I have realised that the following keywords do not affect the individual note of a chord.
\\vol
\\pdur

Is there any way to use these two values in a chord individually?

"<d5_4\\vol[0.2]\\pdur[1] a4\\vol[0.8]\\pdur[2] f#\\vol[0.05]\\pdur[8]>"

At this moment the first note in a chord determines the properties for all notes in the chord. I’ll be honest: this is done mostly because it was easiest to implement. The only way around it is to write separate voices for now, and it’s unlikely to change in the short term. Same goes for the durations of the notes in a chord.

Ok, I understand it!

Thank you for the explanation!

I think that unnoticeable short value could be used for my idea, but the rhythmic calculation is cumbersome.

(
s.waitForBoot({
	
var bwv816_4 = Panola([
"
<b5_4@tempo[150]@pdur[0.9] d5 g3>
<g5 b4 g4>

<d5_512@pdur[57.6] f#4> a_8.....@pdur[1.8]
<e5_512@pdur[57.6]> f#3_16....@pdur[0.9] f#5_8
<g5_4 b4 e3>
<e5 g4 e4>

<b4_512@pdur[115.2] f#> d_8.....@pdur[0.9] d3_4
"
].join(" "));
		
Ppar([bwv816_4.asPbind]).play;
});
)

It would be easier if some arithmetic could be used inside of “”. Then we could write:

<d5_512@pdur[2 ** 6 * 0.9] f#4> a_8.....@pdur[0.9 * 2]

Do you think it seems to be a reasonable notation? I am not sure…

Lilypond and similar notation systems do the same thing. This seems pretty reasonable to me. Even if you were to add things like strumming, or different velocities for each note, this are still properties that apply to the chord. A chord is a single unit that happens to be multiple notes.

Incidentally @shiihs - while I have’t used it seriously yet, I like what I’ve seen of Panola. One of my medium term projects is to create a class that will take pattern output and use it to drive InScore using Guido notation (it requires quite a bit of work elsewhere in the pattern library unfortunately, which is an ongoing thing).

I think that would make this kind of notation a lot more natural in SuperCollider.

@prko
Arithmetic inside the properties sounds like a useful proposal, but unfortunately sclang is not the easiest language when it comes to text parsing (well… that, or I’m not enough of a programmer to understand how to do it properly). If only someone would develop a decent general purpose parsing library in sclang…

As a workaround, I do arithmetic in sclang and substitute it in the string, e.g.

"<d5_512@pdur[mydur] f#4>".replace("mydur", (2**6 * 0.9))

It’s not ideal, but at least you don’t need to do any manual arithmetic.

@cian
I’m interested in “live” notation as well. My experience with InScore, however, has been mixed… it seemed nice at first, but then showed performance problems with many elements on the canvas, and - worse - seems to be unmaintained at the moment. (i.e. there are no very recent commits and I got no reaction at all to bug reports that were blockers for my use case back then). In the end I used the godot game engine which I drove from supercollider using OSC messages. That worked out even better than what I could have achieved with InScore (but it has no built-in music notation of course).

Instantiating a Guido stream probably wouldn’t trigger those same problems though, so things might work out just fine.

Looking at the github repo for InScore, the last commit was in June. 3 months doesn’t seem like enough to declare it dead. I’ve found the developer very responsive in the past when I’ve posted to the mailing list. He may just ignore the issues list.

I have an unfinished parsing library for SuperCollider. Maybe I’ll finish it one of these days.

@shiihs
.interpret evaluates strings.

"3 + 3 * 3".interpret

.interpretPrint evaluates strings and prints it.

"3+3*3".interpretPrint

I have looked your Panola.sc a bit. I am not sure if I understand the structure correctly because I have not sufficient experience in writing classes. I do not know C++.
Anyway, the properties of notes in Panola seem to be analysed, and only digits seem to be concatenated by inspecting the characters in txt.do in pr_unroll_find_inner. I think users can directly write arithmetic symbols inside the properties if you use .interpret in txt.do.

However, I am not sure if it is possible.
I never thought that we could notate score with pitch names in SC before knowing Panola… It is just amazing that you made Panola.

Using interpret in a domain specific language is dangerous. Suppose one offers a web interface where people can input Panola strings. A user with bad intentions now inputs “rm /* -rf”.unixCmd or something along those lines. After Panola interprets that string, the web application might be dead :slight_smile:

A user with bad intentions now inputs “rm /* -rf”.unixCmd or something along those lines.

I have never imagined such cases. Now I understand why you do not use .interpret method.
The following would be a question which would sound foolish. Could these harmful strings be removed?

".systemCmd.unixCmd Pipe( File)  unixCmdGetStdOut runInTerminal"
.replace("unixCmdGetStdOut", "ignore")
.replace("systemCmd", "ignore")
.replace("unixCmd", "ignore")
.replace("Pipe", "ignore")
.replace("File", "ignore")
.replace("runInTerminal", "ignore")

I am sorry if I bother you with nonsense ideas,

What I asked in the previous post is non-sense.
The whole strings related a class or method must be erased.
It would be great if using regular express resolves this, but I could not find a good way.

My solution was a monadic parsing library which worked pretty well, but currently only exists as a proof of concept. Probably not that much work to turn it into a finished quark, but more time than I have currently.

Compared to regular parsers, monadic parsers are surprisingly fun to work with.

@cian looking forward to seeing it jump into existence some day

Some code that I have which does something similar, but for drums:

Two patterns here that take drum tablature and turn it into a stream of events:

  • Ptab
  • PbindTab

The first will take something like ```Ptab(“x__x|_x_x”) and will return this as a stream with rests inserted appropriately. The second does the same thing, but updates a Pdef that you’ve already defined with Pbindf.

Useful for techno/house etc, particularly when I’ve finished some other work that adds swing to patterns in a fairly transparent fashion.

I also have some other classes (Pdrum/PbindDrum) that do the same thing, but with an array of amplitudes (so a 0 creates a rest event).

They should all work, and they’re (poorly) documented. Let me know if you find any bugs.

1 Like