MIDI and OSC into Analysis UGens

Hi!

I am trying to extract features from incoming MIDI and OSC data. I would like to treat them not as single value, but as time signals, therefore it would be meaningful to calculate the RMS, Slope, Median Filter, etc of these signals.

From this topic I have made the following code:


(
MIDIClient.init;
MIDIIn.connectAll;
)

MIDIFunc.trace(true); // post all messages

// create a variable on the language for the allocated server control buses

~slider0 = Bus.control(s, 1);
~slider1 = Bus.control(s, 1);

// write the incoming midi values to the control buses

(
MIDIdef.cc(\controller, {
	arg val, num;

	case
	{ num == 14 } { ~slider0.set(val/127); }
	{ num == 15 } { ~slider1.set(val/127); }
	{ true } { nil };
});
)

//
{Out.kr(2, Slope.kr(In.kr(~slider0,1)).poll); Out.kr(3, Slope.kr(In.kr(~slider1,1)).poll);}.play

s.scope(numChannels: 4, zoom:0.125, rate: \control)

The signal that I am getting is composed of spikes of values and not continuous ones…

Is this right? How can I get a continuous signal?

JACK MIDI works on the audio clock. It doesn’t connect directly to a MIDI device, but you can connect applications. So you just need a command line like a2jbridge. (You would still need to turn it into an audio port in jack to be able to use it as audio in SC.)

OSC is certainly possible, but I do not remember software that does just this. Maybe you can write one tiny program in Rust or C?

------===----

By the way, there is a very interesting JACK audio “metadata” called “Voltage Control.” Many applications are adopting it, and I think SC should have it. I’m not sure about the details of such implementations on the SC side, but it would be very good, and you, for example, could use such ports for this kind of thing.

The issue is that the MIDI data themselves are discontinuous.

MIDI sends discrete messages. Between messages, the signal stays at the last-set value – a flat horizontal line (also known as “zero-order hold”). This is literally what you get from MIDI CCs.

The 0 slope that you’re seeing is this zero-order hold.

In most synths, you don’t hear the discontinuity for two reasons: 1/ the messages come in quickly, with a small delta each time – our brains gestalt-ify this into a smooth curve, and 2/ usually the synth applies a smoothing function before passing the new value to the parameter.

A smoothing function could be as simple as LPF.kr(in, 8) – or use a lower filter frequency for a more gradual change.

~buf = Buffer.alloc(s, 1024, 2);

~bus = Bus.control(s, 1);

(
r = fork {
	var x = (sin(Ptime() * 1.5) * 0.5 + 0.5).asStream;
	loop {
		// this simulates the discontinuous MIDI input
		~bus.set(x.next);
		exprand(0.05, 0.12).wait;
	}
};

a = {
	var in = In.kr(~bus, 1);
	RecordBuf.kr(
		[in, LPF.kr(in, 8)],
		~buf, loop: 0, doneAction: 2
	);
	Silent.ar(1)
}.play;

a.onFree {
	r.stop;
	defer { ~buf.plot };
};
)

JACK MIDI will not solve this problem, because MIDI data are inherently discontinuous, and they will still be discontinuous via JACK. Same for OSC.

hjh

2 Likes

I forgot SC doesn’t have JACK MIDI.

Do you guys think, as a general tool, JACK MIDI and CV (Voltage Control) ports could be of interest in SuperCollider? They are a regular tool in the Linux app world, but SC was never Linux-centric. Since they work on the JACK audio clock, their latencies will be way lower than those of OSC.

I think it would be a good enhancement.

It will only work if you try to make those signals behave as audio signals. It will not be a precise measurement, but at least it will not be a disaster. Try Lag for a starter,

Ah, ok, got the point! Thanks a lot!!!

I will try the tweak, but for what I am doing I think I will need to switch from a MIDI controller to something that samples the signal somehow close to an audio rate…

AFAICS a “voltage control” port in JACK is just an audio port with a descriptor attached. If I’m reading it right, you’d just connect it to a SC input port. Range mapping would be up to the user (for that matter, this is true of MIDI as well).

Some of this is off-topic. OP is interested in a higher-rate control signal (such as analog voltage → DC-coupled soundcard → SC audio input) and control voltage would be relevant, but the JACK feature seems only descriptive and not to have any special features for control voltages. JACK MIDI won’t improve the situation for the OP’s case because the message rate depends on the hardware controller. Maybe JACK MIDI’s timing is better, but it won’t interpolate values in the incoming data stream, so IMO talk about JACK MIDI is definitely off-topic here. Maybe valid in another thread.

hjh

1 Like

Yes, it would make sense when connecting with other applications, as safety is not to make a mess and hurt the ears.

The SC_Jack file in the SC codebase does not mention “voltage control” metadata, but there are some sketches for implementing other metadata supported by Jack.

I’m unsure if this interface is completed or how it should be dealt with in the language. A Voltage Control output would just be a normal audio output in sclang? If not, what would change?

Please discontinue discussion of JACK features in this thread.

The OP has a specific question. Let’s please stick to that in this thread, thanks.

hjh

1 Like