paulrosen / abcjs

javascript for rendering abc music notation
Other
1.94k stars 285 forks source link

My gchord changes #1026

Open seisiuneer opened 4 months ago

seisiuneer commented 4 months ago

Here are all the gchord feature changes and enhancements I added for my tool.

gchord now scales its timing slot size (1/8th note, 1/16th note, or 1/32nd note supported) based on the length of the control string, the meter, and the gchordbars value.

I'm also supporting an optional gchord divider parameter after the control string to force either 1/16 or 1/32 note resolution if someone has a shorter pattern than would kick off the automatic timeslot scaling.

For example, here are two gchord patterns forced to use 1/16th note resolution even though they only have 8 timeslot entries:

%%MIDI gchord fz5cz 2 %%MIDI gchord GHIJghij 2

Also adds optional gchordstress and gchordduration dynamics scalers:

The volume dynamics of the gchord backup pattern may be set using the following %%MIDI command:

%%MIDI gchordstress stress_pattern

Where stress_pattern is a sequence of floating point numbers that have a 1-to-1 correspondence to the %%MIDI gchord control string entries.

Each value in the sequence multiplies the %%MIDI bassvol or %%MIDI chordvol playing volume of each corresponding gchord entry by the specified value.

The scaled values are limited to a range of 0 - 127.

If the number of values in the stress_pattern is less than the gchord pattern length, it will automatically be filled out copying values from the start of the stress pattern as required to match the gchord pattern length.

For example, here is a pair of gchord and gchordstress commands for a reel where the second half of the pattern is played quieter:

%%MIDI gchord fzczfzcz %%MIDI gchordstress 1.0 1.0 1.0 1.0 0.5 0.5 0.5 0.5

%%MIDI gchordstress can also be used as an inline MIDI command:

[I: MIDI=gchordstress 1.0 1.0 1.0 1.0 0.5 0.5 0.5 0.5]

Stress scaling if the gchord command string contains numbers

If your gchord string contains numbers, then you need to account for the number of beat slots that each entry in the gchord actually takes and create stress scale entries assuming the first slot is the note itself and additional rest entries have been added to fill out the note time.

For example, the following gchord string with only 4 entries with duration scaling numbers:

%%MIDI gchord f2c2f2c2

For the purposes of stress scaling needs to be considered as this expanded string with 8 entries that has additional injected z rests to fill out the time for each scaled entries:

%%MIDI gchord fzczfzcz

With the stress scale values only applied to the non-expanded entries and not the injected z rests:

%%MIDI gchordstress 2.0 1.0 2.0 1.0 2.0 1.0 2.0 1.0

Applying stress scaling to the rest entries will not break anything (they are silent), but using this format for the entries may make it easier to match them up to the original gchord string.

%%MIDI gchord Duration Scaling

When a gchord command is found in the ABC, a default duration map is generated for each entry in the gchord pattern, assuming one beat unit, either 1/8th, 1/16th, or 1/32nd note depending on the gchord divider (described below) for each entry, unless the entry is followed by a number, in which its duration will be the number of beat units specified by the number.

If you wish to override the default duration map, the duration of each of the notes in the gchord pattern can be changed using the following private %%MIDI command:

%%MIDI gchorddurationscale duration_scale_pattern

Where duration_scale_pattern is a sequence of floating point numbers that have a 1-to-1 correspondence to the total beat length of the %%MIDI gchord control string entries.

Each value in the sequence multiplies the default duration, by default an 1/8th note unless specifying a gchord divider (described below), of each corresponding gchord entry by the specified value.

If the number of values in the duration_scale_pattern is less than the gchord pattern length, it will automatically be filled out copying values from the start of the duration scale pattern as required to match the gchord pattern length.

For example, here is a pair of gchord and gchorddurationscale commands for a reel where the second half of the pattern is played with longer notes:

%%MIDI gchord fzczfzcz %%MIDI gchorddurationscale 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0

%%MIDI gchorddurationscale can also be used as an inline MIDI command:

[I: MIDI=gchorddurationscale 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0]

Duration scaling if the gchord command string contains numbers

If your gchord string contains numbers, then you need to account for the number of beat slots that each entry in the gchord actually takes and create duration scale entries assuming the first slot is the note itself and additional rest entries have been added to fill out the note time.

For example, the following gchord string with only 4 entries with duration scaling number:

%%MIDI gchord f2c2f2c2

For the purposes of duration scaling needs to be considered as this expanded string with 8 entries that has additional injected z rests to fill out the time for each scaled entry:

%%MIDI gchord fzczfzcz

With the duration scale values ideally only applied to the non-expanded entries and not the injected z rests:

%%MIDI gchorddurationscale 2.0 1.0 2.0 1.0 2.0 1.0 2.0 1.0

Applying duration scaling to the rest entries will not break anything (they are silent), but using this format for the entries may make it easier to match them up to the original gchord string.

Automatic filling out of gchordstress and gchorddurationscale patterns

Here are some fully specified gchordstress and gchorddurationscale patterns for 4/4 meter:

%%MIDI gchordstress 2 1 1 1 2 1 1 1 %%MIDI gchorddurationscale 2 2 2 2 2 2 2 2

As described above, if the gchordstress or gchorddurationscale patterns are shorter than the gchord pattern, they will be filled out by copying values from the beginning of the pattern as required to match the gchord pattern length.

Here are some shorter gchordstress and gchorddurationscale patterns that are simpler than the above, but will achieve the same result.

%%MIDI gchordstress 2 1 1 1 %%MIDI gchorddurationscale 2

Also added the fix that allows %%MIDI vol 0 to work. Previously, it wasn't silencing a note as it should.

Also includes adding an optional octave shift parameter (with sanity check range limiting) on %%MIDI bassprog and chordprog, for example:

%%MIDI chordprog 24 octave=1 %%MIDI bassprog 32 octave=2

The octave shifts for the chordprog also work nicely with the gchord chicks and arpeggiated chords including with inversions.

In my tool, I have the gchordstress and gchordduration scale prefixed with abctt: but removed that for the PR so it would be a first class gchord extension.