alda icon indicating copy to clipboard operation
alda copied to clipboard

Add function for merging voices

Open UlyssesZh opened this issue 4 years ago • 9 comments

piano:
V1: [c16 e g e c e g e | c f a f c f a f | d f a f d f a f | c f a f c f a f |] * 2
V2: [(vol 50) r16 (vol 55) r (vol 60) r (vol 65) r (vol 70) r (vol 65) r (vol 60) r (vol 55) r] * 8
(merge "piano V1" "piano V2")

It is extremely convenient when used together with gradual attribute changes and pedals:

piano:
V1: [c16 e g e c e g e | c f a f c f a f | d f a f d f a f | c f a f c f a f |] * 2
V2: [(pedal 'on) (vol> 50) r4 (<vol 70) r16 (vol> 65) r8 (<vol 55) (pedal 'off) r16] * 8
(merge "piano V1" "piano V2")

What inspire me with the idea is that there are often some "simile" marks in musical scores indicating that the following is played in a similar style.

UlyssesZh avatar Apr 09 '20 00:04 UlyssesZh

| is already used for bars

elydpg avatar Apr 09 '20 00:04 elydpg

@elyisgreat I didn't mean to use | to mark merging. As can be seen, I used (merge "piano V1" "piano V2"). Here | are just barlines.

UlyssesZh avatar Apr 09 '20 00:04 UlyssesZh

Ah. Nvm then; did not read carefully enough

elydpg avatar Apr 09 '20 05:04 elydpg

This is a very interesting idea, but I don't know if voices are a good fit for it. One of the characteristics of voices is that each voice has its own attribute values. That is, an attribute change in one voice should not affect the attribute values of the other voices.

daveyarwood avatar Apr 09 '20 11:04 daveyarwood

I think I might be interested in discussing other ways to do what you're describing, which is basically, writing all of the notes out first, and then writing the corresponding attribute changes (volume, etc.) underneath on a separate line, like you would in sheet music. I think that might be a very nice way to work, especially in the future when we have gradual attribute changes.

daveyarwood avatar Apr 09 '20 11:04 daveyarwood

I wonder if this could be represented as a sort of "operator" on an event sequence?

Something like (syntax TBD, this is just off the top of my head):

[c16 e g e c e g e | c f a f c f a f | d f a f d f a f | c f a f c f a f |]
& [(vol 50) r16 (vol 55) r (vol 60) r (vol 65) r (vol 70) r (vol 65) r (vol 60) r (vol 55) r]

The idea is that the second event sequence is like an "operation" that modifies the first. The operation would be something like interpersing attribute changes (and maybe other events?) into the first sequence.

daveyarwood avatar Apr 09 '20 11:04 daveyarwood

I was thinking about this a little bit this morning and an idea popped into my head.

The idea is that each Alda voice could have a corresponding automation, analogous to automation tracks in DAW programs. Essentially, the automation would be a collection of attribute values over time. Any note in the corresponding voice that occurs somewhere in between two of those automation values would use the intermediate value that falls along the line between those two values.

I like the idea of using voices to represent this concept, but the behavior doesn't exactly map over, like I mentioned above. But it's still useful to think of automation as being like a "voice," so I'm imagining that it could be like a companion to each voice. The syntax I'm imagining is A1:, where the number is expected to match the number of a voice in the group.

So if I wanted to express a trumpet playing a C major scale, while crescendoing from 20 to 100, I could write it like this:

trumpet:
  A1: (vol 20) r2.. (vol 100)
  V1: c8 d e f g a b > c2.

Here, A1 is the "automation track" for voice 1 (V1). It says that at the start of the voice, the volume should be 20, and then a double-dotted half note later, the volume should be 100. As a result, each note in the scale would be progressively louder, following a linear progression from 20 to 100 over the duration of a dotted half note.

This feels clean to me, although it doesn't fully address the spirit of @UlyssesZh 's original example:

piano:
V1: [c16 e g e c e g e | c f a f c f a f | d f a f d f a f | c f a f c f a f |] * 2
V2: [(vol 50) r16 (vol 55) r (vol 60) r (vol 65) r (vol 70) r (vol 65) r (vol 60) r (vol 55) r] * 8
(merge "piano V1" "piano V2")

I think the idea there wasn't to automate a linear progression between values (i.e. you might see intermediate volume values like 51, 52, 53...), but rather to allow the specific volume values (50, 55, 60, etc.) to be written separately from the notes. I think you could technically do that with automation, the same way you would for mix automation in a DAW: you could have multiple data points for each specific value, so that the lines end up being flat. Something like:

0       50
1000    50
1000    55
2000    55
2000    60
3000    60

In other words, the volume automation would be a flat line at 50 from 0-1000, then an immediate jump to 55 and a flat line at 55 from 1000-2000, and so on.

The corresponding Alda syntax for the automation voice would be:

A1: (vol 50) r2 (vol 50) (vol 55) r2 (vol 55) (vol 60) r2 (vol 60)

Which might be a little tedious / cumbersome. I suppose there could also be specific events that put the automation into different "modes," which might make the above easier. Something like:

A1: (mode 'flat) (vol 50) r2 (vol 55) r2 (vol 60)

I could imagine there being other modes for other (non-linear) types of progression algorithms, like some sort of curve instead of a straight line between values. (mode 'linear) vs. (mode 'bezier) or something like that. (mode 'linear) could be the default.

daveyarwood avatar Oct 20 '20 12:10 daveyarwood

I think the automation syntax (A1 etc) is better than the syntax I provided previously (the merge function), but the automation syntax has a drawback. Say, sometimes we need to add literally a lot of attribute changes: dynamics/gradual attribute changes, pedals, slurs. Then, we may want to use multiple automation tracks attached to a single voice.

UlyssesZh avatar Jul 16 '21 04:07 UlyssesZh

Great point! I agree, it should be possible to have multiple automation tracks per voice.

We could solve this with syntax. Maybe you could (optionally) follow the A1 with an identifier. So if you have only a single attribute to automate, you could do it like this (same as above):

trumpet:
  V1: c8 d e f g a b > c2.
  A1: (vol 20) r2.. (vol 100)

And if you have multiple, you could do something like this:

trumpet:
  V1: c8 d e f g a b > c2.
  A1vol: (vol 20) r2.. (vol 100)
  A1pan: (pan 0) r2.. (pan 100)

daveyarwood avatar Jul 18 '21 17:07 daveyarwood