Workshop video proposal: self-timed maps

13 views
Skip to first unread message

Joseph Malloch

unread,
Sep 16, 2022, 2:51:41 PM9/16/22
to dot_mapper
Here is the final proposal video (from me), presenting a proposal for enabling self-timed / periodic map updates. Feedback is very welcome!

Travis West

unread,
Sep 27, 2022, 2:40:45 PM9/27/22
to dot_m...@googlegroups.com
I really like this proposal. I may watch the video again and have some more comments.

Early thoughts:

What about temporal recursion? Or maybe you can change the period of a periodic block from within a periodic block?

To get around the time unit question, we could has msec, sec, minute, hour, etc functions that take a number and convert it to the internal time representation (seconds), or something similar. Maybe unit postfixes could be supported?

It would be nice to have an xox style method of setting non-uniform repeating patterns.

Something that would not fit into the periodic model might be an xox style sequence specification like [1,0,0,1,0,0,1,0,1,0] but where each number is a probability that an event will be emitted on that step.

Including functionality like this really begs the question for me, where do you stop? It makes it easy to do some things, but the mapper scripting language is still very limited and at some point you have to step outside of it and make a device. This relates to my concern that maps are secretely devices, or that devices should be able to serve as maps, or something...

Ideally periodic blocks should smoothly support live coding in some way. E.g. if I live edit the arpeggiator example to change the pattern or add more pitches, the local variable i should not be reset when the map updates?

Do vectors support non-integer (interpolated) lookup? If so, the proposed envelope constructor could simply return a vector (or something that acts just like one), and use square brackets for lookup.

What about envelopes with curved (exponential, logarithmic, sigmoid, ease in/out, ping-pong ball, etc) stages?

What about ridiculous breakpoint automation with dozens or hundreds of stages? Does the syntax need to support that ergonomically, or should that be assumed to be computer generated?

Maybe it would be more convenient to have env(targets, durations), where each argument is a vector? Can we have vectors of vectors?

Can we pass functions as arguments? Then we could also have a vector of curve lookup functions that take an argument from 0 to 1 and produce a curve shape...

I start to feel a little bit confused about variable scope. Is y just global? Can you declare a variable anywhere? What would its scope be? It's not always clear with curly brace syntax...

I had a bunch of other thoughts but I will start a new thread as I think they are a bit tangential.

TW

On Fri, Sep 16, 2022 at 2:51 PM Joseph Malloch <joseph....@gmail.com> wrote:
Here is the final proposal video (from me), presenting a proposal for enabling self-timed / periodic map updates. Feedback is very welcome!

--
You received this message because you are subscribed to the Google Groups "dot_mapper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dot_mapper+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dot_mapper/8aae98fb-c52c-4707-af01-a8367723e61cn%40googlegroups.com.

Joseph Malloch

unread,
Sep 29, 2022, 10:20:36 AM9/29/22
to dot_m...@googlegroups.com
Thanks for the feedback Travis – I’ll try to quickly answer some of your questions below:

What about temporal recursion? Or maybe you can change the period of a periodic block from within a periodic block?

Yes I was envisioning that the period could be changed at any point through expression evaluation, convergent mapping (the period is one of the source signals), or editing map metadata (user variables can be changed through the property API). Perhaps the pattern syntax is confusing and it would be better to make it explicit that the period will be reevaluated:

pattern = [2,1,1] * 300;
pitches = [60,62,64,65,67];
periodic (pattern[i]) {
   i = miditohz(pitches[i]);
   i = i + 1;
}

This would free up vector periods for polyrythms/phasing/other fun stuff (rather than declaring multiple periodic blocks) and simplify some expressions. It would make arpeggiator shuffle look more complex though.

To get around the time unit question, we could has msec, sec, minute, hour, etc functions that take a number and convert it to the internal time representation (seconds), or something similar. Maybe unit postfixes could be supported?

Steve and I used unit postfixes in our past brainstorming of temporal processing. Your function idea would be faster/easier to implement though! Anyone have a preference (with justification)?

It would be nice to have an xox style method of setting non-uniform repeating patterns.

Can’t we just do this with a pattern vector – something like this?

xox = [1,0,0,1,1,0,1,1];
periodic (500) {
    y = xox[i] ? x$0;
    i = i + 1;
}

Something that would not fit into the periodic model might be an xox style sequence specification like [1,0,0,1,0,0,1,0,1,0] but where each number is a probability that an event will be emitted on that step.

xox = [0.1,0,0,1,1,0.5,0.5,1];
periodic (500) {
    y = uniform(xox[i]) ? x$0;
    i = i + 1;
}

Including functionality like this really begs the question for me, where do you stop? It makes it easy to do some things, but the mapper scripting language is still very limited and at some point you have to step outside of it and make a device. This relates to my concern that maps are secretely devices, or that devices should be able to serve as maps, or something...

I’ll address the map vs. device question in another message, but your point is a good one. I think my focus on edge cases may have made the proposal seem fancier than intended. It is important that libmapper remain lightweight for embedded applications and supporting high throughput in terms of messages/sec, but I think that periodic processing is an important low-level feature that makes sense to add – in fact it has been on the roadmap for more than a decade :) The support for arpeggiators & sequencing, etc. basically comes for free once we add periodic updates so I think it makes sense to explore these applications a bit and see if they could help inform syntax design.

In my prototyping the “block” syntax ended up being the simplest but if anyone has a better suggestion please share!

Ideally periodic blocks should smoothly support live coding in some way. E.g. if I live edit the arpeggiator example to change the pattern or add more pitches, the local variable i should not be reset when the map updates?

This is already supported – you can edit user variables using the property API without recompiling the expression. We should extend this a bit to allow changing the length of a vector though. We should also get UIs to use this method for tweaking variables rather than editing the entire expression.

Do vectors support non-integer (interpolated) lookup? If so, the proposed envelope constructor could simply return a vector (or something that acts just like one), and use square brackets for lookup.

Not currently but this is could be added since we already support interpolation of historical samples. Should we also support fractional indices for source signals (and eventually instances)?

What about envelopes with curved (exponential, logarithmic, sigmoid, ease in/out, ping-pong ball, etc) stages?

Perhaps the "env" function should be renamed to something like “linearMultiRamp” to avoid having to solve this now? Or we could go ahead with periodic processing without envelope support and continue exploring envelope syntax.

What about ridiculous breakpoint automation with dozens or hundreds of stages? Does the syntax need to support that ergonomically, or should that be assumed to be computer generated?

Beyond extending the maximum character length of our expressions (which we will have to do anyway if we add blocks) this should be fine. What sort of ergonomic support were you thinking of?

Maybe it would be more convenient to have env(targets, durations), where each argument is a vector? Can we have vectors of vectors?

We don’t (currently) support vectors of vectors so this isn’t possible. That is why I went with the varargs approach in my proposal.

Can we pass functions as arguments? Then we could also have a vector of curve lookup functions that take an argument from 0 to 1 and produce a curve shape...

Not currently.

I start to feel a little bit confused about variable scope. Is y just global? Can you declare a variable anywhere? What would its scope be? It's not always clear with curly brace syntax...

Variables are declared implicitly and are always global with the exception of variables declared in a reduce function which have local scope. Variables that are assigned from instanced quantities (e.g. an instanced input signal) are global in scope but will have instance-specific values.

I had a bunch of other thoughts but I will start a new thread as I think they are a bit tangential.

I’ll try to respond to your other thoughts soon!

Thanks,
Joe

Reply all
Reply to author
Forward
0 new messages