Hi all,
I am working on a function which treats a String as a series of Dictionary look-ups in a Dictionary which has Strings as keys and Events or Event-modifying Functions as values.
Here is a minimal version of it.
(
f = { |string, dict|
var s, modIndices;
s = string.copy;
s = s.split($ );
s = s.collect({ |item| item.separate });
s = s.collect({ |beat|
var numMods = beat.select({ |item| dict[item].isKindOf(Function) }).size;
var actualBeatSubdiv = (beat.size - numMods).reciprocal·;
beat.collect({ |item|
case({
dict[item].isKindOf(Event)
}, {
dict[item] ++ (dur: actualBeatSubdiv)
}, {
dict[item].isKindOf(Function)
}, {
dict[item]
})
});
}).flatten(1);
modIndices = s.selectIndices({ |item| item.isKindOf(Function) });
modIndices.do({ |item|
s[item - 1] = s[item].value(s[item - 1])
});
s.removeAllSuchThat({ |item| item.isKindOf(Function) });
s;
}
);
(
d = Dictionary[
"c" -> (note: 0),
"#" -> { |ev| ev[\note] = ev[\note] + 1 }
]
);
f.("cc c#", d);
// -> [ ( 'note': 0, 'dur': 0.5 ), ( 'note': 0, 'dur': 0.5 ), ( 'note': 1, 'dur': 1.0 ) ]
This works well with the “#” character, but doesn’t work with “♭”, as the latter is non-ascii. As per the String help, non-ascii characters are composed of multiple Chars.
"#".size // -> 1
"♭".size // -> 3
As such, the following returns unwanted results. The nil’s and incorrect duration below are a by-product of the fact that “♭” is composed of multiple Chars.
e = Dictionary[ "b" -> (note: 11), "♭" -> { |ev| ev[\note] = ev[\note] - 1 } ];
f("bb b♭");
// -> -> [ ( 'note': 11, 'dur': 0.5 ), ( 'note': 11, 'dur': 0.5 ), ( 'note': 11, 'dur': 0.25 ), nil, nil, nil ]
Any thoughts on how I can use both ascii and non-ascii characters in my String-to-Events function?
Either I need to completely re-think my approach, or I need a method similar to String:separate which will take, e.g., “b♭” and return [ “b”, “♭” ].