As I mentioned during the last Zynth Club I would start to program a Ctrldev for the Behringer X-Touch. It’s been a challenging experience as I’m not a real programmer but hobby self learned. I’ve now got it so far that it is worth sharing my results.
I still need to clone the repository and issue a pull request, but these is my next steps.
I’m keeping to the Macke Control Standard and I will introduce options later for specific devices, I’ve already looked at Ardour to how this could work, with feature adjustments.
Enjoy the video (I had to shorten it, so a couple of finished features are missing)
The code will be available to others some next week.
That is super cool! It’s good that you used Mackie protocol as that should open up the opportunity for other controlled to be integrated.
Many are. I don’t remember having any formal training in programming. As Manuel would say, “I learned it from a book”.
I wonder how the faders are mapped? They could be mapped to audio mixer channels or to audio chains. Chains can be removed, added and moved so there isn’t a direct correlation between chains and audio channels in the mixer. It’s something that we should consider. I considered it when implementing the Launchkey Mini 3 integration but I don’t remember how I implemented it.
They are mapped to audio mixer channels, purely by accident. I don’t understand the difference but I consider it would be easy to change at this point in time.
Adding and removing of chains will be automatically updated, but I haven’t tested it yet. I’ve also put a limit of to handle 16 channels at the moment as Zynthian has this set. I will also add logic to future proof it, I’ve already set a comment where it should go.
Encoder assignment with the LCD displays is really cool feature, not on the video, to be able to set parameters without going through the UI, I got panning already working.
I can add, remove and move chains and my controller shows the same as in the uni mixer display (wow I got that right without trying ), but take a look at the photo it shows the CH 4 (not dynamically created ) and the chain id as 08 for the sel channel. Both circled in red. The chain was moved
Zynthian has a 16 (stereo) channel audio mixer. Each time a chain is added it is assigned the next lowest available audio mixer channel. MIDI only chains don’t get mixer channels. Each chain is has a chain id which is assigned when the chain is created. Chain id and mixer channel may differ. So, adding and removing chains will result in chains using out-of-order mixer channels.
So the question here (and the coder in me is unlikely to like the answer):
What workflow and behaviour do we want for MIDI binding to mixer controls?
We currently assign to zynmixer channel strips which has no obvious correlation with which chain that is nor the display position of the chain.
Do we want the first external hardware controller to always control the left-most displayed audio (non-MIDI-only) chain?
Or do we want it to map to the first displayed chain (no matter whether it is MIDI-only and hence have no effect) so that we have a direct correlation of hardware faders to chains? (I strongly dislike this option.)
Or do we want to assign control to a chain and then be able to move that chain, keeping the same hardware fader so that you can end up with them out of order?
Or… there are may options.
My gut feeling is that the external controller should map with its left most fader controlling the left most displayed audio chain and that subsequent faders should control subsequent audio chains, e.g. with a snapshot with displayed chains:
That sounds right to me but I am open to ideas. There are technical issues to resolve with the above user workflow/behaviour, such as do we move the MIDI binding as we move chains? Do we move mixer channel association? etc.
Also, do we store this info in each new chain we create which may require additional manual (or rule-based automated) configuration? Is it stored globally? Is it stored and recalled with snapshots?
I am doing some work on the mixer and chains so this may be a good time to consider this.
I like your ideas and clear desctiptions.
Given your example I would like:
Fader 2: Chain 2
Fader 4: Chain 4
Fader 5: Chain 5
So that what i see on the screen corresponds to the fade location on my x-touch (or whatever controller)
If I want to have the audio channel lined up as 1,2,3,4 (your example), then I as user have to put the midi channels at the right end. So as the last chains. (this could be done in your prefrence too)
(I would be nice if I could set the chain order on the screen afterwards but OK, not really nescessary)
Even nicer would be if the MIDI channels also can be controlled by the X-touch. In this way I can control my external piano and Fantom 08 (the last on I use as usb audio device; in and output)
@riban thank you for your thoughts, I do have a plan where you will not need to change your code base, so please don’t start changing anything yet. My idea is to create multiple views (mixer, midi chains, audio chains, instrument chains and perhaps all chains) we have enough buttons to make this possible, Ardour has something similar.
I hoping to have a little demo by at the end of tomorrow so that everyone can see my idea.
So back my Band practice, the drummer has now finished setting up .
The work I am doing with the mixer should make it more flexible. I won’t initially change the behaviour. Be aware that a solution should satisfy any hardware controller, not just the X-touch.
It will be possible to control MIDI parameters too so this scenario needs considering.
Some users may want to place an external MIDI only device between audio chains, e.g. if they regularly use their external piano but less often use a zynthian software synth. Maybe @maartmaart’s suggestion to map absolutely makes sense here. A user can put their MIDI-only chains at the end of the don’t want them to appear on their external control surface. Also, it kinda makes sense that putting a MIDI-only chain between audio chains suggests the desire to treat it similar to the audio chains, i.e. control volume, etc.
Thanks for the feedback. It really helps to clarify ideas. Keep them coming.
Short explanation: When I use the NanoKontrol 2, the main fader on the screen is controlled by the fader at the chains+1 fader. So if I have 4 chains, the fifth fader on my NanoKontrol is the main fader. This is is not what I want to have on my X-Touch…
You’re both right the end user should have the right to choose where the Master Strip goes. In the Ardour mackie device settings it shows MasterFader [Yes/No]. Multi device support is very important to me. Perhaps later on, we could control all of these settings in to the WebUI.
e.g. from Ardour for X-Touch
Name value=“Behringer X-Touch”
DeviceType value=“MCU”
Strips value=“8”
MasterFader value=“yes”
TimecodeDisplay value=“yes”
TwoCharacterDisplay value=“yes”
Extenders value=“0”
MasterPosition value=“0”
GlobalControls value=“yes”
JogWheel value=“yes”
TouchSenseFaders value=“yes”
HasSeparateMeters value=“yes”
IsXTouch value=“yes”
More Settings for different compatable Mackie Controls can be found here.
@riban@jofemodo Thanks for your input on “chain_manager.get_chain_by_position”, it is the way to go, and look there, it has the filters (I am listening even if it took a while for the penny to drop). I’m enjoying learning how zynthian works.
The difficulty I’m having, in “def update_mixer_strip (self, chan, symbol, value):” I’m getting the mixer channel and I’m not sure how to turn this into the controller fader position, am I correct that I would get the chain_id from chain_manager.get_chain_id_by_mixer_chan(chan) and then find the position in chain_manager.ordered_chain_ids or is there a better way?
And of course I need to do it the otherway around from positiion to zynmixer.set_level(fader_channel, …
@riban I’d love to hear what exactly you’re doing or thoughts are “The work I am doing with the mixer should make it more flexible” and if it simplifies my task.
It certainly should simplify your task. I am splitting zynmixer to have input channel strips on one jack client and mic busses on another. This will improve latency in some scenarios.
I’m also adding effect send controls which has been requested and I certainly want. We won’t need to route to another chain to create a group and each chain’s level will be adjustable to each group mixbus.(Currently they all have the post-fader level.)
The mixer will also be dynamic in size so reducing the overhead of running 17 channel strips even when only one is required. It will also allow more mixer strips if required (because you always need just one more!).
It will remove the UI association with zynmixer channel indices (which will become ad-hoc) and may remove the chain/position mapping. (I haven’t got there yet.)
The current implementation of zynmixer is very flexible but with the benefit of a few years of experience using and coding it we can be more pragmatic.
I want to implement mono chains in a better way. (Currently chains are stereo with the ability to mono to both outputs but that results on multitrack recording having stereo tracks when you want mono.)
The zynmixer channel strip will become a processor which makes the chain management similar, e.g. you will be able to move the fader position, not just the effects position.
Adding, removing and moving processors should be simpler and more consistent.
The reporting graph will look more busy but few people look at that. We will retain the default internal normalisation of channel strips to main mix bus to reduce the quantity of unnecessary jack routes but adding post-fader effects will not increase latency (like it does now).
As you can see, this is quite a significant change to zynmixer and we will need to look at the controller device drivers to ensure they work with this new structure as well as matching the desire behaviour discussed in this forum.
Possible other benefits may include the ability to have chains that bypass zynmixer and ability to convert chains between types, e.g. remove the synth from a chain to turn it into an audio input chain. I am not sure these have sufficient benefit to implement but it is worth considering.
Could you add AUX Send(s) and possibly BUSs as well, I’m assume these should be dynamically added, if needed
The mixer will also be dynamic in size
Will faders be able to be added to all channels, Effects/Aux Sends, Bus Output(?), Each Output (some Audiodevices have multiple outputs), Effects returns, etc ?
Okay for me that means, I’ll concentrate on the chains with ordered_chain_ids and the different chain types as that won’t change. And I’ll wait with the rest.
When you have am early release, do let us know, I’m assuming you’re doing in your own fork, I’m happy to test.
We kinda already have this - well, sort of… and my change should mkae it work like it should. You can already route a chain to any direct output or any other chain with the chain options audio out menu. The sends will go to mix buses that in turn can be routed anywhere, e.g. main mix, direct out (aka aux send), etc. So the send becomes the preferred mechansim for common effects, groups and aux send. Indeed, it is the aux send that I miss. My 8 of my 10 outputs are sitting idle whilst everyone listens to the same stereo mix - it is a crime!
The zynmixer channel strip will be a processor in every audio chain and return/group so there is the capacity to have faders in most of these positions. We must constrain our design though. It needs to be simple to comprehend and serve the primary purpose of the zynthian which (I am oftern reminded) is not a mixer (even though I use mine as such).
I will put it in a dev branch on the main zynthian-ui repo when there is enough of it to make sense and let you know. It will be a branch from vangelis.
That might not be needed in the future but stick with it. I will ensure backwards compatibility and we can tweak things as needed when we have something stable.