Open emuell opened 1 month ago
My wishes were around scales, either with some scaled
function that maps integers to scale degrees like
cycle("0 2 [4 5] [6 4]"):scaled("minor"):transposed("d")
Or have the scale object contain common mapping functions that can be used without lambdas, I like this a bit more because you can define a scale at one place and reuse it.
local cmin = scale("penta", "c")
cycle("0 2 [4 5] [6 4]"):map(cmin.notes)
cycle("0 2 [4 5] [6 4]"):map(cmin.chords)
It might be nice to also support something like
local cmaj = scale("major", "c")
cycle("ii V I"):map(cmaj.chords)
But the issue with these approaches I think is that just taking the chords from scales is not very interesting, you often want to invert a chord, extend it or use something out of the scale at some point. If there was some more general chord mapper that would be really handy.
For example we could make use of the Target
field from events to build chords on root notes, or do something similar with strings mapped to chords without target or root note.
cycle("c4:m7 f3:7#11 c3:M9i1"):as_chords()
I like this one:
local cmin = scale("penta", "c")
cycle("1 2 [4 5] [6 4]"):map(cmin.notes)
cycle("1 2 [4 5] [6 4]"):map(cmin.chords)
This would work out of the box with the suggested mapping feature.
chords
needs an extra argument though (number of notes), so it must be a member function.
But the issue with these approaches I think is that just taking the chords from scales is not very interesting, you often want to invert a chord, extend it or use something out of the scale at some point. If there was some more general chord mapper that would be really handy.
For example we could make use of the
Target
field from events to build chords on root notes, or do something similar with strings mapped to chords without target or root note.cycle("c4:m7 f3:7#11 c3:M9i1"):as_chords()
Actually would be nice if the existing note chord's syntax could be directly used in cycle as well. I had borrowed that from Tidal already.
cycle("c4'm7 f3'7#11 c3'M9")
I guess this could be added directly to the cycle impl - without any custom mapping?
Good point about the :
operator:
Both should be passed as arguments to a map lambda:
local cmin = scale("c", "minor")
local function my_scale_map(value, target)
local degree, note_count = value, target
return cmin:chord(degree, note_count)
end
cycle("I:3 V:3 IIV:5"):map(my_scale_map)
quite verbose, but I personally don't have a problem with that.
With the basic mapping working, I'll start looking into automatically mapping chords as c4'maj
in cycles now and allowing chords as values in maps:
local cmin = scale("c", "minor")
cycle("i v vi iv"):map(function(context, degree)
return cmin:chord(degree)
end)
Once that's done, we can start thinking about how to make some of the more common things, like chords, easier to map.
Right now, only note strings and integers are supported in cycle. e.g:
cycle("c4 c5")
orcycle("48 60")
But it's possible to use arbitrary strings as identifiers, and floating point numbers in the mini notation too:
cycle("bd sn")
Such identifiers are currently ignored and will emit nothing.
The easiest and probably most obvious way to map such identifiers to notes (or later other event types) could be using a map function which takes a table or function as argument:
table:
function:
I think 1. could be implemented quite easily using the following rules:
map_with_scale
funtions for that.@unlessgames you had some whishes idea here, if I remember well. Any idea how this could look like?