String handling inside of framelib networks

WOOHOOOWWWW!!! Super nice!


So - I think I can solve the object name issue, so this is probably the last interface question. I see your point, but there needs to be a tag set for the object to do something useful. String parameters default to “” which is not useful. The general principle for argument ordering in FrameLib in Max (and in theory pd) is that the more important a parameter is to set the earlier it should be in the argument list, so to me it makes sense for this to be the first argument (it can’t be placed anywhere else). Many max objects have ambiguity with arguments, because they are not named (unlike attributes/parameters).

Off the top of my head I can’t think of another FrameLib object where you can’t use it with default parameters or purely by setting arguments, but maybe I’m wrong about that.

Thoughts? Counter arguments?


Ah I see! It is also perfectly OK to have the first arg as the tag, you probably see the broader picture a million times better than me, a noob frameliber. My arguments were mostly in the mindset of cloning [combine], but there is I guess a lot more to consider when designing for the fl ecosystem.
By the way, since the result must always be a tag, shouldn’t the name have “tag” in it somehow? No concrete idea ((apart from the not so nice “tagfactory”)) atm, just thinking…

By the way, since the result must always be a tag, shouldn’t the name have “tag” in it somehow? No concrete idea ((apart from the not so nice “tagfactory”)) atm, just thinking…

Technically a tag is just the first bit used to determine which parameter something will operate on - but we are operating on the data (the string part) - tags are also strings, but all the other objects with tag in the name focus on the tag part (e.g. fl.tag~ which adds tags to numbers or fl.combinetags~ which combines tagged frames).

I don’t think I have any watertight arguments, but I somehow resonate with what Balint suggested, I’m inclined to like the /tag buffer syntax.

If I had two options, I would intuitively go for -

fl.joinstring~ samples in1.in2 /tag buffer /padding 2 3 /trigger ins 1 2

I might be bringing too much of the outdated Max subconscious into the game, but it somehow feels more comfortable to address the buffer name first and then to tag it later.

I’m not sure in which other contexts this object will be used. Maybe there will be other use cases where you’ll need to combine strings, but then tag it with something else. Again, not sure.

If this object is made specifically for combining buffer names for dynamic use with polybuffers, then I think it can also be called bufsel~ (buffet select) or selbuf~, however cringe it sounds.

Then it would encapsulate everything you need to accomplish that goal and leave the rest to more comprehensive string manipulation objects.

True that, good point.

I like this idea! Again, I lack the proper perspective, but I don’t know where else you would like to create string tags on a frame-level, as when you swap between buffer references. So why not just focus on that task, maybe it doesn’t need to be anything else than a buffer name maker (you don’t know cringe until [fl.buffernamemaker]!). In case you go for a generic string maker, I like joinstring or concatstring, though I don’t feel we can’t find better ones.

Other examples would be to dynamically create a string to use as a tag for an object like fl.tag~, fl.dispatch~ or fl.untag~. A fixed tag to me is a bad idea - much like the way the [folder] object puts the symbol append before each filename, because it assumes you are going to use it with a [umenu]…

And FWIW I think my preferred name (after some thought) is fl.makestring~.

1 Like

Haha, yeah that’s a classic! I am all for general-purpose string-making.

Sounds good to me. Would be one of the first things I would look for if I had the task of making a string.

1 Like


So - I think this also deals with simple cases raised by @james.bradbury. I have plans for a larger (probably named) string table with two way lookup that can’t be altered at frame-rate (for instance for long fixed or slowly changing sample lists where message rate would be fine for changes) but that’s a little way off.

This also allows you to map string parameters (enums) to numbers as you wish, which is useful (e.g. filter modes etc.)

1 Like

I was considering adding a scale parameter to the lookup so you can lookup with indices, or 0-1 (normalised) - thoughts?

1 Like

Looks great. This would immediately solve my problem. I’m making a concert instrument that combines the spirits of a multisampler and a granular synth.

Fun fact: I prototyped with a single buffer and yesterday got 3K simultaneous voices on M1 air.

Thank you so much, Alex!

1 Like

3K sounds like a lot! Was that multi-threaded at all?

I presume also that you are currently running under Rosetta 2? I’m actually able to build native now, so that might change things a bit.

1 Like

Haha yes, I had multithreading enabled and the build I got was from James, not sure if it was specifically for M1. The official version I downloaded crashed Max upon opening, but the build from James works well. No crashes so far.

I think because I compile with AVX off which is usually the source of many woes with M1 beyond adjusting the code itself.

I hadn’t used FrameLib much recently till I wanted to play with a 24 channel granular synthesiser at NOTAM. I had 24 streams of 100ms grains every 30ms using around 10% CPU with multi-threading on. It is extremely efficient for that sort of thing I’ve noticed and even more noticeable compared to my almost 10 year old laptop I swapped out for this M1.

1 Like

The important thing regarding M1 and Max is whether you have upgraded Max to 8.2 which should run native on M1 processors. It looks like it might also be an option to run a universal app under Rosetta (How to force a native M1 Mac app to run as an Intel app instead | Macworld). So you’d need both to have Max 8.2 on an M1 machine, and have that option off to be running native.

The release here for SSE will run under Rosetta 2 (the aux version will not because AVX is not emulated under Rosetta 2). That includes some fixes that were not in v1.0.

However, I can also now build FrameLib native for arm64, and that may run faster, but I don’t know because I am not on M1 myself. I will aim to get a version up somewhere soonish.


FYI this was using the 8.2 version running natively with a native ARM build of FrameLib.