Re: [Loopdub-devel] Synchronizing MIDI controls with LoopDub
Brought to you by:
radarsat1
From: Nick T. <nh...@gm...> - 2007-12-28 04:47:39
|
On Dec 27, 2007 8:47 PM, Stephen Sinclair <rad...@gm...> wrote: > Hi Nick, > > I had never thought of supporting devices which can auto-position > their knobs, but what I did consider and planned on doing sometime > soon was implementing a sort of "pick up", so that when the context > switches (a loop is loaded or program is changed), and the knob and > "virtual knob" become unsynchronized, I planned on having the value > stay put until the MIDI value passes through the position of the > virtual knob, to avoid having values jump all over the place when you > touch a knob. > Yes, so I had read. These two features are not mutually exclusive, fortunately; both of them can exist simultaneously without interfering with each other. Thus, both auto-positioning and non-auto-positioning controllers will be supported in the best way possible, without any special configuration. > Committed. > Thanks! > We'll have to work out, in the future, some way of selecting a device > for CC-output and possibly a different device for clock output. > Yes, you're right. I hadn't considered that. > On the subject of device selection, I still like the simplistic little > panel of device-buttons at the top of the screen, making configuration > really fast, but as features are added, I can see that it may not > suffice for all cases. It's also sort of a waste of screen-space to > list MIDI devices that aren't in use.. it might be better to have a > single button that cycles through available devices, or something > similar.. I have yet to implement a drop-down menu, but the silly > little GUI system I devised doesn't handle overlapping areas very > well. > I like it as well, and I also see the potential need for change. One possibility would be to simply put the MIDI device choices inside .loopdub.conf. This, of course, would assume that users will want to select the same MIDI devices each time. Would you say that that is a reasonable assumption? > Actually I think it would be better to do this the other way around. > In my experience, moving more "intelligence" to the GUI is usually a > bad idea. > Yes, you're right. I presented the idea as the most obvious one, or perhaps the simplest change to the code. I do not think that it's a very good idea. > I don't really consider that the controls store the MIDI > values, they only store their own GUI-slider value, which is most > cases is the same as the MIDI-knob value, but, as you point out, can > become desynchronized. So the problem is that the actual MIDI-slider > values are not really stored anywhere... Perhaps we really need a > separate representation for the MIDI knobs. > Actually, storing the MIDI slider's current value isn't necessary, nor does it even make sense, since we can't know what the true "current" value is. We can know what CC message we last received; however, this doesn't necessarily match the slider's current value on the actual hardware controller. For instance, you could move the slider, unplug the MIDI cable, move the slider again, and plug the cable back in; now, the slider's current value does not match the value we have set for it. In a less pathological case, suppose that we have just connected the controller, and one of its sliders is in the middle of its range. The user hasn't yet moved the slider, so we don't know where it is, and whatever default value we choose for it may or may not be correct. So, in summary, we cannot store the MIDI slider's current value, since we cannot know it; we can only decide what to do based on the current internal slider setting and the individual CC messages we receive. With that in mind, we should use the following algorithm (independent of any class design): 1. When the value of a slider changes as a result of the user manipulating the GUI slider, or from an internal program setting, we send the new value to the MIDI controller. This will obviously be a no-op if the controller does not support MIDI sync. 2. When we receive a CC message, if is exactly one tick away from the current internal value, then we update the value. If it is not, then we know that the MIDI slider and the internal slider have drifted apart, and the user needs to get them back into sync before we will respond to their CC messages. This algorithm handles both MIDI synchronization and slider pick-up without any conflicts, including all pathological cases. Now, the question is: what class design is best suited to this algorithm? One thing that both the current design and your proposal miss is the notion of "the value of a slider." In the current design, the current value of the GUI slider is taken to be the correct value for the slider, which will always be true. However, once you start talking about decoupling the GUI from the rest of the program, you can no longer rely on the GUI slider to provide that information. So, any design must store the current slider value somewhere other than in the GUI slider. My proposed design puts the information in the LoopObs. Your proposed design does not put it anywhere. The other thing that my design does is provide the framework needed to implement the above algorithm, in the form of the CtrlSource parameter. For (1), whatever class initiated the change calls SetController with source = SRC_INTERNAL or SRC_GUI. For (2), in the case when the CC value is adjacent to the internal slider value, the MidiControl class calls SetController with source = SRC_MIDI to adjust the internal slider. Anyway, those are my thoughts on the subject. I think that my proposal is probably the simplest, and therefore best, way to do things; however, if you have a better way, I can still be swayed. :-) Now, just one more thing, before I forget. I mentioned earlier that I was using buttons on my MIDI controller to toggle the echo effect on and off. In detail, this is how it works. When the button is toggled on, it sends a CC message setting the feedback to 64. When it is toggled off, it sends a CC message setting the feedback to 0. If MIDI pick-up is implemented as I have described above, then it will break this scheme, since the button never moves through the intermediate values between 0 and 64. Since I personally have no use for MIDI pick-up, perhaps it would be good to have an option in .loopdub.conf to disable MIDI pick-up. But, of course, what about people with non-auto-positioning controllers who also want to use this scheme? For these people, the more general solution would be to enable/disable MIDI pick-up for individual sliders. However, this would be a rather complex thing to do for such a corner case, so I propose that we do not implement it unless somebody specifically needs it. |