[SOLVED] Global Transpose Device (using LOM)
Hi community!
How can i made a device that globally transposes all tracks (audio and midi)?
I think that I will need 3 devices: 2 receivers (for midi and audio tracks) and 1 “master” sender (or vice versa, I’m a little confused), which will control the transpose of all tracks on which the receivers are open.
Many possibilities.
The most straight forward I see is:
1 master device that sends the transpose amount to other devices (simply using [send])
For midi tracks: 1 midi effect device that simply intercepts incoming midi and add the transpose amount to it
For audio tracks: 1 audio effect that takes control of a "transpose" parameter of an external pitch shifting effect (unless you want to handle the pitch shifting yourself in max)
So, what are you struggling with? Seems like you have everything you need.
For the audio part, if you want to change the pitch of each individual clip instead of using an audio effect, according to the LOM, you can list all clips of a track with clip_slots (for session view) or arrangement_clips (for arrangement view, note that this function is only available from Live 11). Then, for each clip, you want to modifiy pitch_coarse, and maybe pitch_fine to actually change their pitch.
I am building something like this at the moment and I transpose to different scales. I got one master device, one midi tranpose device and one drum rack transpose device. But it‘s part of a much larger project.
But for your scenario: Since you are transposing everything, why aren‘t you just pitching your master with one pitch device?
MARC ASSENMACHER, I'm beginner in max/msp and it's not entirely clear to me how to do this)
Marc Assenmacher meant to just throw a pitch shifting audio plugin (vst/au/...) onto your master track, instead of pitch shifting each track individually. Max is not even needed.
TFL, I'm just learning ) I want to understand how I can implement this in exactly this way, so that the pitch of each individual clip on the track changes with one knob. Also, if I do this using vst and other methods, I lose quality, all FX work differently, but not one gives the same quality as if I changed the pitch of the audio clip.
I would suggest you to do the Max Basic Tutorials to familiarize yourself with the Max environment and objects. You can fnd them in the Max documentation (in Max: Help menu, then "Reference". Check the "Getting started" tab, then the Max tutorials. You can definitely abuse the search bar of that window).
Then, read the documentation regarding M4L and the Live API (look for "Creating Max for Live Devices", "Live API Overview", "Live API Abstactions", "Live API Examples"), and maybe study existing M4L devices.
Then you can come back here with a more precise question, with an example of what you've done so far and where you're stuck at.
arrangement_clips returns a list of all clips of the track. So you need to iterate through that list to select each clip one by one, and send them "set pitch_coarse $1", one clip at a time.
I don't know how that list is formated (I only have Live 10 which does not recognize the "arrangement_clips" message), but have a look at zl objects (especially [zl.iter]) to process listsn and also [trigger] to organize operations.
Also, you can use "live.path this_device canonical_parent" to target the track the device is on, instead of targeting the selected track.
And you can also post your patches here so we can help you more conveniently: either select relevent objects then click the Edit menu, then "Copy compressed", and paste here in your post, or you can also directly upload the .amxd file here.
Note:
Using "live.path this_device canonical_parent" is an easy way but will not work anymore when your device is part of a device group, since the canonical parent then is the group device.
MARC ASSENMACHER, TFL
I have several options but I'm confused or I can't use get/set pitch_coarse on some objects. Here is one of the options, but here I have to choose one of the clips (I can't explain the whole patch, because I just took half of it from a video on youtube)
As it arrangement_clips gives you a list like "id 7 id 8 id 9 id 10 id 11 id 12 id 13 id 14", you can use [zl.iter 2] to break this list in a succession of lists of two items (id 7, id 8, id 9, and so on) and basically iterate through it very fast.
Here is an example to change the pitch of all clips in session mode (again, I only have Live 10 where arrangement_clips don't work). But you could easily adapt the logic for clips in arrangement view.
EDIT:
I implemented the same logic in your patch (but can't test it as I only have Live 10) :
It's more about taking time to practice, learning, breaking a problem into smaller parts, and searching through that forum and the documentation than genius.
Nothing fancy here, just basic Maxand LOM logic.
I didn't tested it so it might not work, but you get the concept.
TFL, Cool! this is exactly what I was looking for. Thank you so much for your help!
You've already spent enough time helping me, and I'm not comfortable asking you to, but maybe you can help me with one more question.
Imagine that I want to shift the start_marker, BUT randomly for each clip on the track, is it possible?
I did this based on the previous patch, but it shifts all clips evenly, also I haven't figured out how to tell it the length of the clip within which the device will be able to shift the start_marker, and implemented a simple offset that returns to 0 after reaching 4.
Here's a patch, take a look if you have time.
Thanks again, I appreciate your help!
It's a matter of adding two objects and modifying one. In your current patch, you send the same offset value for every clip. I just added a "b" in the last trigger object (which becomes [t b b l]), and that bang will trigger the [random] object for each clip.
I think you are really missing how [trigger] objects and [zl.iter] works. [zl.iter] will split the list of all the clip ids into individual messages, one for each clip, and send thel very fast. What comes after zl.iter will then be triggered for each clip id, one after the other. If you connect a message to the [zl.iter] output, you will only see the last output, but if you connect a [print] to it, you will see that for each list of clips it receives, it actually sends one message for each clip.
I am building something like this at the moment and I transpose to different scales. I got one master device, one midi tranpose device and one drum rack transpose device. But it‘s part of a much larger project.
indigo card
TFL, Yes, maybe I'm really missing a lot of things, I'm just starting to learn max, this is my second attempt. But I still can't always understand the logic of how to work with it, I also don't know many objects. unfortunately, I can't find an answer to all the questions on the forums)
Maybe I didn't explain exactly what I mean a little.
This patch does shift the start_marker of all clips to a random position, but this position is the same for all clips, I would like to shift the start_marker of each clip to a random place inside each of the clips. I mean, the start_marker of all clips should be different, but it may coincide with some of them.
What I understand is: you want to shift the start_marker of clips to a random position, each clip having its own random position. This is exactly what the patcher I posted in my previous post does. Or at least it what it's supposed to do. I didn't test it in situation. By looking at it again, I assume it might need some modifications. See below.
However, I don't understand this sentence: "the start_marker of all clips should be different, but it may coincide with some of them.". Do you mean that, because start_markers are set randomly, they are supposed to be at different position for each clip, but sometimes two clips can have their start_marker at the same position (because random is, well, random, and two random values can sometimes be the same value)? If so, you might ask yourself what kind of random you want. Do want your start markers to be at any position in the first 4 beats of the clip? Or do you want them only at on-grid positions such as 0.5, 1.2, 2.0, etc..? That would determine the way you generate random values, and the likelyness of two clips having their start_marker at the same position.
Here is an example which will randomly set the start_marker of each clip at one of the first 16 beats.
TFL, Hey bro, I hope you're okay!
I found one bug in the previous patch, maybe you can help me with this?
The fact is that every time I change the value in the device, this value is added to the previous one, and so every time the parameter is changed.
Is it possible to make the device access the original pitch of clips and apply the given value to it, and with each change it accesses the original pitch of clips by adding/subtracting a new value to the original pitch of clips?
I am building something like this at the moment and I transpose to different scales. I got one master device, one midi tranpose device and one drum rack transpose device. But it‘s part of a much larger project.
pikashow download
I found one bug in the previous patch, maybe you can help me with this?
The fact is that every time I change the value in the device, this value is added to the previous one, and so every time the parameter is changed.
True! But it is not a "bug", it works as expected: adding a value to the current pitch value.
Is it possible to make the device access the original pitch of clips and apply the given value to it, and with each change it accesses the original pitch of clips by adding/subtracting a new value to the original pitch of clips?
It is definitely possible but it requires more patching and logic. If we decompose what you want in smaller blocks, we have:
- At launch (or when the device is inserted on a track): get the current pitch for each clip and store it as the initial value (as a list using [zl.reg], or a collection using [coll], or a dictionnary with [dict])
- When you set the new transpose value, add it to the stored initial pitch value and set the result as the current pitch.
- You might need to add a button to "set pitch back to initial values", and another to "store current pitch as initial value", that would be helpful if you want to change the initial value, or if you add new clips to the track.
There is another way that would help to keep everything more simple (it's just a matter of modifiying 1 or 2 objects of the current patch): make all of your clip with a pitch of 0 as default. And if you want to pitch your clip as a default, export the clip with the desired pitch value and use that new pithed clip that will have a pitch value of 0. I hope it makes sense.