Euterpea / Euterpea2

Euterpea version 2
zlib License
220 stars 71 forks source link

[Question] Strategy for swing feel #32

Closed battermann closed 5 years ago

battermann commented 5 years ago

Hi,

it would be nice to have a PhraseAttribute for specifying a swing feel that works something like this:

data SwingDur = En | Sn | Tn

data PhraseAttribute  =  Dyn Dynamic
                       ...
                       | Swing SwingDur Double

The double value (in range: 0.25 - 0.75) specifies how hard the swing feel should be. E.g. Swing En 0.5 means no swing at all - straight eighths. Or e.g. Swing Sn 0.6 is a slight swing on the sixteenth notes, where the first of a pair of sixteenth notes takes 60% of the duration of an eighth note and the second takes 40%.

I have been thinking about how to implement/apply this when transforming a Music value into a Performance and I think it is not completely trivial.

A first attempt:

Not sure if it is this simple. There are probably a few edge cases and as always the devil lies in the detail.

However it would be great to have this feature because it can give the music a more human feel.

donya commented 5 years ago

This is not a simple problem. In fact, Euterpea's lack of time signature representation makes it quite tricky to implement in a general sense while still making everything sound reasonable. After all, even at the phrase level, it's impossible to know what beat the phrase starts on, which affects how the swing should work. Enough assumptions need to be made that it isn't really appropriate for inclusion in the core library.

On a somewhat related side note, the strong need for awareness of metrical position in jazz (whether for swing or other reasons) means that any realistic performance handling has to take place as a another layer on top of Euterpea-style representations to allow storing extra information. This is one of the reasons I created Jazzkell, which is another small library that sits on top of Euterpea that has explicit representations for onsets and time signatures.

Regarding extra constructors, there is already a way to specify custom Control nodes (Phrase is just another kind of Control):

data Control = ... | Custom String

The custom Control can then be handled as part of a custom performance algorithm (see the playC function and the PlayParams data type).

battermann commented 5 years ago

That makes a lot of sense.

Thank you for clarifying this for me.