simple in the sense that MIDI output itself is not a deep or complicated topic.

most of the SC stuff about list processing, time structures, event generation &c is not at all specific to MIDI, or to internal synthesis. (it is even executed in a totally separate process/environment from audio synthesis / processing.)

so in a nutshell, i’d say:

not really. go through the Patterns tutorials. see Patterns Guide 08 for Pattern->MIDI syntactic sugar, or MIDIOut for the lower-level API. everything you learn about sclang that’s not specific to server stuff, will be applicable.

1 Like

you want to forward everything besides cc 120?

MIDIdef has filtering arguments following the function:

MIDIdef.cc(
	\ccFiltering, {
       arg msg;
	   // do something with the message
	}, 
    chan: (1..15),
    argTemplate: { arg num; num != 120 } 
);

or you can respond to everything and manually test the msg

1 Like

Okay, thanks

One more thing while I’m here, and this is probably really stupid so feel free to ignore if so, but I’m having an unusually frustrating time trying to send pitch-bend data. This is my dumb little demo code, where \bend isn’t doing anything and I’m not sure why (the range is so hyperbolically huge—OVER 9000—because I wasn’t sure if I just wasn’t able to audibly observe its output):

(
Pbind(
	\type, \midi,
	\midicmd, \noteOn,
	\midiout, m,
	\chan, 0,
	\midinote, Prand([66, 67, 69, 65, 68],inf),
	\dur, Pexprand(1.05, 0.07, inf),
	\bend, Pexprand(30,9000,inf),
	\sustain, Pbrown(0.01, 1.0, 0.125, inf),
	\amp, Pexprand(30,90,inf)/127,
).play
)

sorry, not in a position to test easily (i don’t use MIDI much myself) but typically pitch bend data is 14 bits so [0, 16383]

@qwoned ok yea, couple things

  • seems that midi bindings for pattern can only deal with one midi message type at once. or that’s all i can see so far. too bad. there might be a way to do it or you might just need an explicit updae function. (i tried Pchain but no dice.)

  • so e.g. it works to have one pattern doing \noteon and one doing \bend.

  • for \bend msg type, you want to use \val for the value. it’s in [0, 16383] with 8191 at center. this is normal for pitchbend.

MIDIClient.init;
m = MIDIOut(0);

(
~note = Pbind(
	\type, \midi,
	\midicmd, \noteOn,
	\midiout, m,
	\chan, 0,
	\midinote, Prand([66, 67, 69, 65, 68],inf),
	\sustain, Pbrown(0.01, 1.0, 0.125, inf),
	\amp, Pexprand(30,90,inf)/127,
	\dur, Pexprand(1.05, 0.07, inf)
);

~bend = Pbind(
	\type, \midi,
	\midicmd, \bend,
	\midiout, m,
	\val, Pexprand(30,16383,inf),
);
)


// this works fine...
~bend.play;
~note.play;

//.... 
~bend.stop;
~note.stop;

// but this unfortunately doesn't work. 
// (AFAICT just creates a new Pattern,
//  with all the key/value pairs medged from the first two,
// same as you had originally.)
Pchain(~note, ~bend).play;

i’m neither a big MIDI user or a big Pattern user myself, so that’s about all i got right now. (i would just use a raw Routine or Clock.sched - more verbose but easier for me as a procedural caveman.

(oh, also: your duration function is weird 'cause it has lo value bigger than hi value.)


@qwoned ok, here’s a caveman version that seems to basically work (though i haven’t closely checked for hung notes)


~note_stream = Prand([66, 67, 69, 65, 68], inf).asStream;
~sus_stream = Pbrown(0.01, 1.0, 0.125, inf).asStream;
~vel_stream = Pexprand(30,90,inf).asStream;
~bend_stream =  Pexprand(30,16383,inf).asStream;
~dur_stream = Pexprand( 0.07, 1.05, inf).asStream;

r = Routine { inf.do {
	var chan, note, vel, bend, sus, dur;
	chan = 0;
	note = ~note_stream.next;
        sus = ~sus_stream.next;
	vel = ~vel_stream.next;
	bend = ~bend_stream.next;
	dur = ~dur_stream.next;
	[note, vel, bend, dur].postln;
	m.bend(chan, bend);
	// kinda dumb/bad way to do sustain. make this a function at least.
	m.noteOn(chan, note, vel);
	SystemClock.sched(sus, {m.noteOff(chan, note); nil});
	dur.wait;
} }.play;

1 Like

I was just going to ask how to synchronize the bends with the noteOn events, and your

does exactly this!! there are hung notes, but I can fix that. Ideally I would implement Scala files—which I don’t know how to do yet—but using \bend could be interesting for ad hoc ‘hybrid’ temperaments (at least that would be my tentative justification for now). And thanks for the tip on the lo/hi duration function, just sheer clumsiness there. I don’t know anything about what SystemClock.sched does yet, either.

Also I’ve been listening to this demo code run for over an hour straight—intermittently emended as live updates come in here—if anyone is curious what @qwoned is all about

oh right. the SystemClock is a way to explicitly schedule something to happen in the future. here it is a terrible, very bad way to make a noteoff. (the nil return value is important, otherwise it will reschedule.) i borked this, didn’t set sus and was probably passing nil as the time delta, hence no noteOffs at all. just changed this above [for the sake of future searchers.] (fixed? dunno.)

1 Like

I’ve slowly been getting more comfortable with SC over the past few months, but I could use some tips now. What are some of the better ways to mix down multiple sounds for output? right now I tend to just rout things to bus 0(and 1 with multichannel expansion taken into consideration) but this has some issues with clipping when many sources are involved. Is there a common method of creating a “mixer” Synth or something to help with equalizing stuff? What I’ve got in my head is something allocating 8(or whatever) audio buses, and then having 8 In UGens in a final mixer Synthdef that get mixed for the final output to bus 0(and 1). Is there a better or more efficient way to do this, without sacrificing control over gain?

Related to this, will I run into issues using one audio bus for multiple sources, like routing multiple Synths through a reverbBus(to go to a general reverb SynthDef)? obviously clipping, if I don’t scale down(and this goes back to my first question), but can you run too many sound sources through a bus?

I’m still learning the lingo so my apologies if this is hard to understand or if I sound crazy

I’ve been trying to figure out how to yield sequences of repeating patterns that repeat an arbitrary (pseudo-random, or whatever pattern might be specified) number of times and change—in real-time (or, ‘generatively’)—not only pitch content but also length and tempo of sequence without having to re-evaluate the line of code. For now, I’ve been writing it like this, e.g:

Pdefn(\notes, Pseq(Array.rand(rand(12), 25, 81), inf))

and a Pdefn for tempo might be written like this, in the same line:

Pdefn(\tempo, Pseq(Array.rand(1, 0.33, 18.6), inf))

but to change the sequence length, tempo, and pitch content I have to arbitrarily trigger it via cmd+return. I’ve been writing it this way for each parameter so that the re-evaluations are synchronized, i.e. \notes changes at the same time as tempo, \legato, \amp, etc.

Is there any way to write this—in a more efficient way—to yield the desired result? I’ve been trying to figure it out for the past several days and am coming up nil, probably because I’m not looking in the right place in the help-guide or something. Maybe something like Pstep or Pclutch? Thanks in advance.

[fwiw, I’m using MIDIOut to an external AU, no SynthDef.]

Also if there is anyway to apply patterns to \program changes in the same Pbind, that would be really great…

You could try using some random patterns, e.g. Pwhite, which will continue to produce a random stream without the need to re-evaluate the code. Or you could use a combination of Pn and Plazy to automatically re-evaluate a function once the stream ends, without having to type command-return

Edit: An example:

Pbind(\degree, Pn(Plazy({Pseq({12.rand}!4, 4)})), \dur, 0.125).play
1 Like

Thanks! However, I’m seeking to randomize not only note order of pattern but also its size and number of repetitions. I was able to achieve the latter, albeit the pattern size still remains static—in the following example the size is seemingly constrained by the specified range of the Pseq (55…66):

Pdefn(\notes, Pn(Plazy({Pseq((55..66).rand, 11.rand)}, 1)))

How would one also randomize the length of sequential notes repeated? Moreover, I understand that perhaps Pbindef would be appropriate if I wanted all of the other parameters to automatically re-evaluate and change—e.g. \tempo, \legato, etc—though I’m unsure how this would be written exactly. Here’s an example of how I’m currently writing it using Pbind:

Pdefn(\legato, Pseq(Array.rand(1, 0.1, 1), inf)); Pdefn(\notes, Pn(Plazy({Pseq((55..66).rand, 11.rand)}, 1))); Pdefn(\tempo, Pseq(Array.rand(1, 1.2, 9.32), inf)); Pdefn(\amp, Pseq(Array.rand(1, 0.5, 1), inf)); a.stop; a = Pbind(\type, \midi, \chan, 1, \midicmd, \noteOn, \midiout, m, \tempo, Pdefn(\tempo), \midinote, Pdefn(\notes), \amp, Pdefn(\amp), \legato, Pdefn(\legato)).trace.play;

Not 100% sure what you mean by “length”. Note lengths (durations) can be varied by setting the \dur parameter with a pattern (e.g., you could use a Plazy for the durations as well)

ah, sorry—I should have indicated “size” instead of length, i.e. the amount of notes in the \notes pattern.

You could replace your (55..66).rand with a function that returns a different sized array each time it is called…

Editing my above example:

Pbind(\degree, Pn(Plazy({Pseq({12.rand}!(8.rand + 1), 4)})), \dur, 0.125).play

This produces a random array of between 1 to 8 notes (the size), and repeats that sequence 4 times before choosing a new array (of a different size)

For fun:

(
f = {Pseq(({2.rand*12 + 12.rand}!(12.rand + 1)).flop(3), 4)};
Ppar([
	Pbind(\degree, Pn(Plazy(f)), \dur, 2, \sustain, 1, \octave, 3, \strum, 0.5)
	,Pbind(\degree, Pn(Plazy(f)), \dur, 0.5, \sustain, 0.5, \octave, 4, \strum, 0.125)
]).play;
)
1 Like

That works! elsewhere I also was given the suggestion of: Pdefn(\degree, Pn(Plazy{Pseq((40..77).scramble.keep(rrand(2, 20)), rrand(2, 15))}), which closer approximates the intended result. I decided to keep the Pseq(40..77) insofar I can more easily indicate and modify registral span of array without needing a transpose function (since I’m doing all this via MIDIOut.

Since you mentioned using Plazy for durations, too, I’m struggling to figure out how to synchronize the automatic re-evaluations for notes with that of durs. For example, each time the note pattern changes its size and its repetition size, the dur of such pattern would change each time, too? Could this be accomplished in the same Pbind?

I’m sure there are lots of (better) ways to do this. Here’s one that seems to work:

(
e = (d: 1);
Pbind(
	\degree, Penvir(e,
	Pn(Plazy({
		e.d = [2,1,0.5,0.25,0.125].choose;
		~size = (4.rand + 1);
		~notes = {12.rand}!~size;
		~notes.postln;
		Pseq(~notes, 1);
        })
	))
	, \dur, Penvir(e, Pfunc{~d.postln;})
).play
)
1 Like

How would one go about retrieving only the elements of an array below a certain depth? (i.e. sub-arrays)

For example, if I had this array:

[1, [2, 3], [4, 5, [6, 7]]]

I would like to be able to get:

depth = 2 : [6, 7]
depth = 1 : [[2,3], [4, 5, [6, 7]]]
depth = 0 : [1, [2, 3], [4, 5, [6, 7]]]

etc.

I’ve been looking at deepCollect and deepDo, but neither of those seem quite right because they operate on all sub-arrays above (and including) a specified depth. I would like to be able to operate only on arrays below (and including) a certain depth.

it’s not particularly pretty, and it doesn’t do exactly what you want, but it might help you partially?

I made an external method:

+ ArrayedCollection {
	removeThese { arg func;
		var i = 0;
		while { i < this.size }
		{
			if (func.value(this[i], i)) {
				this.removeAt(i)
			}{
				i = i + 1
			}
		}
	}

	getFromDepth { arg depth;
		var getFromDepth_func, start_obj;
		start_obj = this.copy;
		getFromDepth_func = { arg obj, func_depth;
			if ((func_depth > 0) && (obj.isArray)) {
				obj.removeThese {|item|
					item.isArray.not;
				};
				getFromDepth_func.(obj.flatten, func_depth - 1);
			} { obj };
		};
		^getFromDepth_func.(start_obj, depth)
	}
}

save this as getFromDepth.sc in the Extensions folder in File -> Open user support directory, and hit ⌘⇧L to re-compile the class library.

a = [1, [2, 3], [4, 5, [6, 7]]];

a.getFromDepth (0); // -> [ 1, [ 2, 3 ], [ 4, 5, [ 6, 7 ] ] ]
a.getFromDepth (1); // -> [ 2, 3, 4, 5, [ 6, 7 ] ]
a.getFromDepth (2); // -> [ 6, 7 ]
a.getFromDepth (3); // -> [  ]

yup, so not exactly what you were after (some of the structure you were looking to retain is lost when getting from a depth of 1), but potentially it might help?

1 Like

Anyone know how I might be able to get info from an array in SuperCollider into a web browser via OSC? For example, I have a dynamic array of Strings in SuperCollider that I’d like to pass to a web browser to be displayed and update when it’s updated. I’ve been using Nexus UI for the past couple years to send OSC to SuperCollider but I’m wondering if there’s a way to get data from SC to the web browser easily for display.

I was vaguely wondering this myself. I think last time I looked into this, I found this prior to shelving the pursuit for later: https://github.com/MylesBorins/node-osc

1 Like

i have had success with making an app in electron and talking to SC with osc.js. (be sure to read the osc.js documentation carefully, because some special setup is necessary to get it to work in electron.)

if/when sclang gets TCP server functionality (not planned currently) then it could work with websockets in a standard web browser.

2 Likes