alda icon indicating copy to clipboard operation
alda copied to clipboard

Nested voices

Open elydpg opened this issue 9 years ago • 8 comments

In 1.0.0rc50, implicit closing was added, allowing voices to work inside variables and event sequences. However, there is a slight issue when it comes to attribute setting. Consider:

piano: (tempo 150) [V1: c4 d e f g1 V2: e4 f g a b1]*2 (tempo 200) [V1: g4 f e d c1 V2: b4 a g f e1]*2

In this segment, the second sequence should play uniformly faster, as the voices were closed and the attribute was applied to the entire instrument. However, when played, the attribute is applied to the second voice, as if the voices weren't closed at all.

elydpg avatar Mar 25 '17 00:03 elydpg

The question here is, under what circumstances should a voice group be considered "closed"?

If you write out the repetition explicitly, you can see what's happening here:

piano:
  (tempo 150)
  V1: c4 d e f g1
  V2: e4 f g a b1
  V1: c4 d e f g1
  V2: e4 f g a b1 (tempo 200)
  V1: g4 f e d c1
  V2: b4 a g f e1
  V1: g4 f e d c1
  V2: b4 a g f e1

The event sequence groupings have no bearing on when voice groups begin and end, so the (tempo 200) belongs to voice 2, the last voice declared. The voice group continues until the end of the piece or a V0: occurs.

To get the desired effect in this case, you could do this:

piano:
  (tempo 150)
  [V1: c4 d e f g1 V2: e4 f g a b1]*2

  V1: (tempo 200)  V2: (tempo 200)
  [V1: g4 f e d c1 V2: b4 a g f e1]*2

or this:

piano:
  (tempo 150)
  [V1: c4 d e f g1 V2: e4 f g a b1]*2

  V0: (tempo 200)
  [V1: g4 f e d c1 V2: b4 a g f e1]*2

I think you might be suggesting that we have scoped voices -- that is, voice groups that are internal to a variable definitions or (in this case) event sequences. This is a compelling idea, and I'm tempted to make it so, but there might be some edge cases as a consequence of doing it that way. Maybe it deserves more thought.

In general, though, similar to the point I made in alda-lang/alda-core#35, nested/scoped voices provide a nice flexibility, but they also add a little too much complexity to the language to be worth it, IMHO.

daveyarwood avatar Mar 25 '17 18:03 daveyarwood

Interesting. How does implicit closing work, anyway?

elydpg avatar Mar 25 '17 19:03 elydpg

It's really more like explicit closing, if you think about it. A voice group is only ever closed when V0: is encountered. The idea is that once you start using voices, any new events that are encountered will be added to the last voice you declared (e.g. V2:) until you explicitly say you're done with the broken-out voices and you want to go back to using a single voice, which we call "voice 0."

daveyarwood avatar Mar 25 '17 19:03 daveyarwood

Huh. So why weren't voices working in event sequences and variables before?

elydpg avatar Mar 25 '17 19:03 elydpg

Context: https://github.com/alda-lang/alda/pull/286 https://github.com/alda-lang/alda-core/pull/1

Voices weren't working in event sequences before because the parser didn't consider it valid syntax. We added voices as a thing that can occur inside of an event sequence.

I don't remember offhand what the bug was with voices inside of variable definitions.

The conversation in the PRs above led to the discovery that we don't actually need voice groups at all in Alda, and we could simplify things by only having voices.

Semantically, when you start using a voice for the first time in a score (e.g. the first V1), it's sort of like you're in "voice mode," which means that whenever another voice is encountered (e.g. V2), that voice will start at the position where the first voice (V1) happened, and with all of the attribute values that the instrument had at that time. When V0 is encountered, that effectively ends "voice mode."

daveyarwood avatar Mar 25 '17 19:03 daveyarwood

The variable issue was referenced in alda-Lang/alda#255 and seemed identical to the event sequence issue.

elydpg avatar Mar 25 '17 19:03 elydpg

I spent some more time thinking about this, and I don't think I'm interested in adding nested/scoped voice groups to Alda, at least not in the "implicit" way that we've been imagining in this issue and alda-lang/alda-core#35.

I don't think it's unreasonable for Alda to have a feature like nested voice groups, but if it did, I would want the syntax to be explicit (something like https://github.com/alda-lang/alda-core/issues/35#issuecomment-289229931) so that it's easy to understand that these are inner voices and not top-level voices.

I'm also not interested in adding new syntax if it can be avoided, so we would want to do it in a way that's compatible with existing Alda syntax. Maybe it could be something like adding (voices) and (/voices) events to alda.lisp, and using them to start and end an internal voice group.

I think this would take a lot of work under-the-hood, though, and I'm not sure it's worth pursuing.

daveyarwood avatar May 15 '17 12:05 daveyarwood

I had some more thoughts about this - see https://github.com/alda-lang/alda/issues/335#issuecomment-753377311

daveyarwood avatar Jan 01 '21 20:01 daveyarwood