slurmulon / bach

:musical_score: Semantic music notation
http://codebach.tech
MIT License
7 stars 0 forks source link

Change beat units to be based on whole note instead of whole measure #19

Closed slurmulon closed 3 years ago

slurmulon commented 5 years ago

Problem

Right now the unit of a beat is scaled to the defined meter/time signature and a single beat unit applies to an entire bar/measure . For example:

@Time = 6|8

!Play [
  1 -> Chord('Cmaj7')
]

will play a Cmaj7 chord for an entire measure, the equivalent of six 1/8th notes.

Likewise, if you had the following:

@Time = 6|8

!Play [
  1/2 -> Chord('Cmaj7')
]

It would play Cmaj7 for half a measure, or three 1/8th notes.

This works well for time signatures with an even number of beats in them, but quickly falls apart when dealing with time signatures such as 5|8, 7|4, etc.

For instance, if you are in 5|8 time and want to play a chord (or whatever) for the equivalent of three 1/8th notes (or 60% of the measure/bar), it starts to become very obtuse:

@Time = 5|8

!Play [
   6/10 -> Chord('Cmaj7')
]

This is also contrary to traditional Western concepts, in which a whole note always equates to four 1/4 notes, regardless of the time signature. It's simply non-intuitive given that most people are trained in and familiar with Western music theory.

Solution

The path of least resistance (and of greatest benefit) is to update Bach such that beat durations are scaled to the traditional concept of a whole note, instead of a whole bar/measure.

Modes

As I see it, there are potentially three modes we could eventually support.

It may be useful for users to be able to decide which mode they want their beat units in, and this could be done at either a global/track level or at a contextual/time-specific level.

But this is a large undertaking and is reserved as a separate task.

:trad

This should be the default mode since it aligns with traditional Western music theory concepts.

This mode means that a beat unit of 1 would represent a whole note (instead of a whole bar like it is now), or four 1/4 notes, regardless of time signature.

This mode works about just as well in time signatures with both even and odd numbers of beats, but can get a little verbose (albeit clear and direct) in time signatures that don't have a quarter note as the base unit (such as 6|8).

:bar

This is the mode that Bach 0.X was/is built around.

A beat duration of 1 equates to an entire bar/measure scaled to the time signature.

So a beat duration of 1 in 4/4 would mean 4 quarter notes, while a duration of 1 in 6/8 means 6 eighth notes.

This is very clean for measures with an even number of beats, but not so great with measures with an odd number of beats.

:meter

This mode means that a beat's duration maps directly with the beat unit defined in the time signature/meter.

So a beat duration of 1 in 6|8 time would equate to a single 1/8th beat.

The advantage of this mode is that it works across all time signatures (even or odd).

It does, however, get a little strange in even common time. For instance, a duration of 1/2 ends up equating to an 1/8th beat in 4|4:

@Time = 4|4

!Play [
  1/2 -> Note('A')
  1/2 -> Note('B')
  1/2 -> Note('C')
  1/2 -> Note('D')
  1/2 -> Note('E')
  1/2 -> Note('F')
  1/2 -> Note('G')
  1/2 -> Note('A')
]

Therefore this mode is arguably best suited for rarely encountered time signatures.

Implications

This is a breaking change and will involve performing a major release to 1.0