One session view track to copy another
Hi, this is my first post on these board so I apologise if I'm putting this in the wrong area or other such novice behaviour.
I'm working on a live idea where when triggering clips in my live set, I can sweep between alternate versions with an encoder. To illustrate the basic principle say you have a track group, you have two tracks inside and you've mapped your encoder to turn the two tracks up and down with inverse values. You hit play on the track group and one they both play, move your encoder from one side to the other and one fades out as the other fades up. If you hit an empty stop clip on the group they both stop.
That's essentially exactly what I want except for the annoying caveat that group tracks don't show any kind of name, making navigating what I'm launching sort of impossible. So I started trying to get creative with some MIDI routing to instead have a track of dummy clips fire off the group track, which is hidden off to the side. It's a pretty limited approach, you can't deal with stopping by selecting an empty clip slot on your dummy clip track.
So what I was wondering is perhaps there would be a way with Max to create a device that essentially linked two tracks. Have a one track "linked" to another, so that when the first is playing a clip, the second plays the clip in that scene. When the first stops with an empty clip slot, the second stops with the parallel empty clip slot. Essentially I'd be using max to build the exact functionality of group tracks as far as playing and stopping goes (not so much the summing of audio), just I'd be able to give names to the clips on the primary controlling track.
Now I've worked with things like Bomes MIDI translator and ClyphX, but sadly have little to no max experience. So I just wanted to ask the community here if that sounds like something that's actually possible with Max? Or are their limits to the way the whole thing comes together that would make that probably impossible?
I'm not going to be so taxing as to ask someone to explain to me how to actually build such a device. But assuming it is possible, if anyone has any starting points or links to good tutorials or such for a newbie they'd like to show me I'd be greatly appreciated.
Excuse the ramble, these things are always so convoluted to try to put into words. Thanks heaps for anyones help.
Ok so I've gotten this far, but there's some fundamental here that I'm apparently missing. I've managed to find a number representing the clip just fired in the given track. I'm then using that to format a path message (which I'm arbitrarily point at track 2 for the time being). So far so good, but the part I don't understand is why the live.path doesn't seem to update where it's focused unless I manually click on this generated message box. Even though this message box is updating, nothing I seem to do to try to get it to automatically trigger and pass this path on seems to work. When I click on it though, it absolutely does. With the newly focused clip I can click on call fire (another thing obviously needing automation but one step at a time) and it behaves appropriately.
Can someone explain to me why this path isn't being passed on to live.path? I've tried layering in "t b l" objects everywhere!
You still need "t b l" before the last message box containing the path.
Hi Broc thanks for offering your advice. Is it something like this that I'm guessing you mean? This is how I understood the logic too and what I assumed should work. Although it doesn't seem to. In this instance, fire is never called. Or at least, I can never observe it doing anything in live. You can see I snapped this screenshot as a clip was flashing (in a "trigger" status) so the relevant pieces are seemingly filling out variables and so on but simply nothing is happening. Can anyone tell me what I'm missing? (by the way I assume there might be a more elegant way to discuss this than me posting screenshots on these forums? Forgive me I'm new to it all).
Do you get any error messages?
(to see them right-click on the device title bar and choose 'Open Max Window').
For posting patches, read this
Ok so a bit of an update, I seem to have discovered a limitation of live.observer I wasn't aware of. It seems able to output some sort of value that it's observing (i.e. which clip slots are being triggered), but it doesn't also output a bang/trigger that in turn can do something with that information. See the attached screenshot (and the error message at the bottom is what I only just realised with the previous configuration that was seemingly my problem).
Yes, here is a quote from the documentation 'Live API Overview'.
"Note: changes to a Live Set and its contents are not possible from a notification. The error message in the Max Window is 'Changes cannot be triggered by notifications'. In many cases putting a deferlow between the notification outlet and the actual change helps to resolve the issue."
Ah that's the information I was looking for, thanks so much. I seemingly missed the part about deferlow as a solution when I was looking through help files. Fantastic! I now have a really simplistic working version of this plugin;
There's some limitations, like follow actions sort of screw the whole thing up (and the live API doesn't seem to give hooks into follow actions at all). Also it's really only based on triggering clips provided there are clips in the controlling track. I.e. triggering blank slots in the controlling track that have clips in the receiving track doesn't always work, but that's not at all what I need it for so I'm ok with that. Stopping clips in the controlling track with blank clip slots totally works across to the receiving track.
One thing I'd like to put together just to make it a little more sophisticated would be to select the track by a drop down (right now it's a numbox for the track number, not something you would always know). However looking at the paste for "Live API Choosers > Browse Tracks" it seems to output an ID no. rather than the track no. I'm not sure how to get from an ID no. to its child "clip slot $1" (whereby you pass in the variable at will).
Thanks again for your help man. I feel pretty pleased for someone making his first patch!
Broc, I'm curious about something in this patch. Are the TBL's necassary after the Observer? Can't the Observer output go straight into the message then into the live.path?
The message box triggered with 't b l' after the observer is required only for testing, ie. viewing the output. To see the value and pass it through you need to send it to the right inlet and then bang the left inlet.
Yeah I've been doing that sort of thing just for my own brain rather than the max patch itself. Helps me keep across whats happening when testing. Can anyone shed some light for me on my questions above? About how with a "id #" for a track I can navigate to it's child clip slot. As presently I only understand how to do this referencing the track by it's number (as in "live_set tracks 1"). Thanks
You need to assign the track id to a live.object and send it a 'getpath' message. This will give you the track path where you can append 'clip_slots x' to get the path of slot x.
ah awesome thanks so much. Max is extremely well documented and the way that you can copy examples right out of the help files is fantastic. However the thing I'm finding as a newcomer at the moment is that I know somethings possible but I just don't know what words to use to search Max's help or even google. So thanks for filling in these little blanks for me I really appreciate it.
To that end, I've been expanding my basic clip launcher to something more elaborate I wanted to use it for. To skip over the details basically I'm moving between two sounds, but every time a new clip (and I check against the last launched number and such) is launched I always swap it back to the one on the first track as soon as the clip plays. This essentially works, but as might be expected there's a couple of milliseconds of delay. Because max has to take the "clip just fired" message and then perform the action (which is moving a macro rack).
Could someone head me on the path to making this action perform a fraction before the clip play? Or a general idea on how to try and remove this delay between the clip play and the action? Or is that something hugely advanced and not entirely possible?
I think the latency problem can be handled with quantization assuming that quantized clip launching is used. Basically the same quantization could be implemented for the target action. So the clip launch (blinking) would just notify the action to start at the next quantization point, in perfect sync with the clip start. Since the quantization points are known, the action could also be started a bit earlier to compensate for possible latency of performing the action.
Yeah quantization is definitely being used. Is there max hooks to get at quantization specifically? I tried implementing a faux quantization with a metro object set to bang ever bar (same as my global quant). It worked the same as waiting for the clip fire really, still a couple of milliseconds behind.
(by the first sentence in the post above I meant that I'm using global quantization in the project, set to one bar)
Unless there's an object or something I haven't come across things are looking a little grim. If I'm understanding this thread correctly, perfect quantization with live for programmatic tasks is near impossible;
https://cycling74.com/forums/perfect-max4live-quantization/
Is there any other object that initiates quantized actions other than metro?
Metro ensures perfect sync with Live's transport when used for example like this
[metro 1n @quantize 1n @active 1]
But the timing of Live API functions is generally not accurate.
Hmmm so I'm discovering. I imagine in a wider variety of applications this would probably be a deal breaker for the idea. I might be able to get by with the small quirk for what I'm doing though (this is all a part of building a custom live performance set). I've set up a sub patch that outputs a bang a 32nd before the end of every bar, a really shoddy way to attempt to compensate a little for the delay in messaging. Seems to work alright, but certainly not millisecond perfect;
If anyone's curious, this is the sub-patch;
As you can see there's an input to turn on and off the gate for output to. I only want to receive these bangs in certain conditions in my patch.
The counter can be avoided by using a single 1 bar metro and delaying its output by 1 bar minus x ("ahead time"). It may also be useful to set the ahead time in milliseconds, ie. independent from tempo.
Hi Broc, sorry a very late reply. I've been busy with other aspects of the project (amongst other things!). So I just had a play with your addition and it seems to work pretty well! I had been thinking about trying to incorporate some kind of delay compensation element, then I could map a controller and if I heard things sounding a little off, bump it up a notch.
However I was wondering if you could help me wrap my head around how it works though? Theoretically if I had a metro sending out a bang at the start of every bar, then ran it through a delay of 50ms wouldn't that make the bang about 50ms late? If my issue is that the bang is already actually coming a touch late, surely I need to compensate in the other direction?
Now it would appear that your patch does absolutely that, I'm just trying to wrap my head around why. I thought I would have to undercut the bar (say going back to my method of about a 32nd before the bar) and then add the delay from there. But it seems you've got a sort of inverse delay?
Thanks for all of your help, I'm still really surprised that I managed to get this idea off the ground seeing as I knew nothing about max when I started.
With a very quick glance, I would say that if every bang is delayed, by 1920 - x ticks, apart from the first bang, it's as if you applied a negative delay to the following bangs. The metro doesn't deliver an absolute clock.