Easy way to get a Bus from Midi Input

Hello,

I was looking in the forum and documentation for an easy way to map a midi note/cc to a control Bus, but the only way seems to be creating a new Bus.control and then define a MidiFunc that calls .set on the bus.

Is there something like this?
Bus.fromMidiCC(cc, channel, maxValue, minValue, curve)

Thanks!

This may help… I only know MIDI half, another will provide the formula for bus control, quite easily, I presume.

// initialize MIDI

(((

	MIDIClient.init;
	MIDIIn.connectAll;

	// trace incoming messages

	MIDIdef.trace; 				/*	turned on by default  */
	// MIDIdef.trace(false); 	/*	turn off  */

	MIDIdef

	(

		key: \x 	/* Symbol, Chars, Integers can be redefined
		key: "x"	/* ...while one have any # of def's named "x"
		//			/* ...and accessible by key via MIDIdef(\x)
		// 			/* ...or MIDIdef.all.at[\x]
		*/														*/*/*/

		,func:

		{
			|velocity note|  	//	[velocity, note] .printAll;
			// |v n chnl uid|  	//	[v, n, chnl, uid].printAll;

			velocity . sign . switch

			{
				1
			}

			{
				// "down action... or clockwise movement of knob"	.postcln
			}

			{
				0
			}

			{
				// "up action... or knobs counterclockwise"		.postcln
			}

			// 	one could, just as easily...

			//	;velocity . booleanValue . if { true } { false }	.postcln

			// 	...where all values above 0 will be interpreted as true
		}

		,msgNum:

		(
			..127		// or whatever you like
		)

		,msgType:

		(
			\control
			// \noteOff
			// \noteOn
		)

		// key, func, msgNum, & msgType are the most crucial arguments
		// channel and uid can be left as nil for *all incoming msgs*
	)

	.permanent_

	(
		// true		// will survive cmdPeriod
		false		// false by default
	)

	// .enable				// new defs always enabled
	// .disable				// temporarily pause def response

	// .free will clear the def
	// .oneShot will make the def self-clear after one use
	// ...a good example is making defining a noteOn responder
	// ...which self-defines it's own cleanup noteOff .oneShot

	;

	[
		MIDIdef(\x).enabled,
		MIDIdef.all.keys,
		MIDIdef.all.values
	]

	.printAll

	.pop

	.size

	.postcln

	;

	// simulate the control switch with Shift+Enter:

	/*
	MIDIIn.doControlAction(val:127, num: 36)
	MIDIIn.doControlAction(val:0, num: 36)
*/)))

It does seem, however, that one would be forced to create the appropriate responder function (MIDIdef is far more versatile than MIDIFunc) and then set the control bus from there… which should be extremely straightforward, nonetheless.

I’ve been working in MIDI for years, and everything above should serve as a decent primer, or reference point… it encapsulates nearly everything one would need.

I can tell you, as straightforward as I can, that the particular style of method that you’re looking for, doesn’t exist, at any rate… and so to map the incoming MIDI data to a control bus, requires some sort of responder (MIDIFunc or MIDIdef).

The only difference between the two, is all MIDIdef’s are accessible globally via MIDIdef.all, using the value passed as the key: argument… whereas for MIDIFunc, there is no such global list of definitions, and this requires one to first assign a variable to the response definition in order make the MIDIFunc object available in the future… otherwise, it will be rendered inaccessible the moment it is created.

Aside from this caveat, both interfaces are nearly identical. They both inherit a working list of instance methods from AbstractResponderFunc, a number of 14 in total, so be sure not to overlook those.

This is true – although the next point is that one could write an extension class to bind a bus and a MIDI responder together.

@nolente The design issue is – if you go with a model of Bus.fromMIDIcc(...):

  • Suppose this method returns a Bus object. When you, later, free the bus, what happens to the MIDI responder? As the caller, you don’t have access to the MIDI responder, because the method returned only the Bus. So you can’t free it by hand. Neither can the Bus object free it. So the MIDI responder will leak (object leak = an object was created but can’t be removed straightforwardly), and it would interfere with a future Bus object that happens to take the same index. So this is bad.

  • You could perhaps design a naming convention to locate responders in the MIDIdef collection – then it wouldn’t be necessary for the method to return it, because there would be a predictable place to look it up.

  • But the best approach, IMO, is to model the bus ↔ MIDI responder relationship in a single object. Then the method would return this object. Freeing the relationship-object would, in one step, free both bus and responder.

… but…

Those two statements seem moderately contradictory :wink: I’d say MIDIdef’s built-in global storage makes it more convenient for some but not all use cases (e.g., in the suggestion to model the relationship, the new object would retain the reference to the MIDI responder; putting it into the global collection would introduce a risk of name collision, which I’d recommend against unless there’s a very good reason).

hjh