Apotome sequencer

This article talks about a browser-based generative sequencer. Seems interesting.


2 Likes

There’s significant work to be done in understanding the ways that DAWs mess with your brain. Not only 12ET and metric grids, but… I see that most of my students have no concept of assembling a track from sections. They see, across the top of the screen, “bar 1 bar 2 bar 3…” and they instinctively create following the timeline. You have practically infinite capability to slice up, edit and rearrange material seamlessly but they’re held captive to the timeline, just like Arabic and African musicians struggle against equal temperament and metric quantization.

This looks massively valuable to expose the ways that DAWs use us instead of the other way around.

hjh

1 Like

I played around with it for a while sending MIDI data to SC. It worked pretty well, althought it seemed to stop playing sometimes.

I’m not very experienced with modular synths. I wonder if students would benefit from having to sometimes work away from the DAW and in a modular envirment. With VCV Rack, modular is now much more accessible.

Hi,
Is there anything that this sequencer does that isn’t possible with Pbind or the Scala Tuning library?

Curious to try it, but wanted to ask the others on this list.

Microtonal midi control of external Hardware requires pitchbend. Does Apotome sequencer take care of this behind the scenes?

Thank you
Bests

I was messing with this the other day, and had a simple example going in SC. I had to switch the instrument in Apotome to “Midi Out”. Also, I’m not convinced my pitchbend calculation is correct - apparently the bend range can be changed, so my 48 is just an assumption - and I sadly cannot tell if this Asmaroneng tuning sounds correct by ear. :slight_smile:

Example...
~pendingNote;
~notes = ();

MIDIdef.noteOn(\apoOn, {
	|note, vel|
	var synth;
	
	"ON:   % [v%]".format(note, vel).postln;
	
	~notes[note].free;
	~notes[note] = nil;
	
	if (vel > 0) {		
		~pendingNote = (
			type: \fm,
			seed: vel.linlin(0, 128, 20, 23),
			midinote: note,
			velocity: vel
		).play;
	}
});

MIDIdef.bend(\apoBend, {
	|bend|
	var bendRange = 48;
	bend = bend.linlin(0, 16384, bendRange.neg, bendRange);
	
	"BEND: %".format(bend).postln;
	~pendingNote !? {
		~pendingNote[\ctranspose] = bend;
		~notes[~pendingNote[\midinote]] = ~pendingNote.play;
	};
});

MIDIdef.noteOff(\apoOff, {
	|note|
	var synth;
	
	"OFF:  %\n".format(note).postln;
	
	~notes[note].free;
	~notes[note] = nil;
});
)

The pitchbend MIDI is sent AFTER the note on - I don’t know if this is normal, and I’m assuming that these are supposed to be connected - the only straightforward way to implement this is to queue the event in the noteOn responder, and then ACTUALLY play it when the bend arrives, so you can transpose.


I think you can probably do everything that Apotome is doing in SuperCollider, especially if you use Charles Célese Hutchins’ TuningLib + Scala. Honestly the Apotome UI is very powerful, and it would still be a major effort to implement ALL of the pattern things in SC patterns - maybe this thread can be a place where people can post clones of individual pieces of functionality?

I have some code somewhere that send midi notes plus bend to do microtonal with hardware, I can post if it would be helpful for anyone.

1 Like

I would be curious to see the code you have for midi notes and pitchbend for microtonal with hardware if it’s not too much trouble…
Thanks much

MIDI tuning example
(
// \finish function is called before Event is played....
Event.parentEvents.default[\finish] = {
	if (~type == \midi and: { ~midicmd == \noteOn }) {
		var detunedFreq, midinote;
		var bendScale = 2;
		var bend;

		////////////////////////////////////////////////////////////////////////
		// Separate detunedFreq into an integer midinote plus a bend amount
		detunedFreq = ~detunedFreq.value; // raw hz, should incorporate whatever scale is being used....
		
		midinote = detunedFreq.cpsmidi;
		bend = midinote - midinote.round(1); // in semitones
		midinote = midinote.round(1);
		
		~detunedFreq = midinote.midicps;
		~bend = ~bend ?? { bend };
		
		////////////////////////////////////////////////////////////////////////
		// Convert bend to midi range, and send to midiout
		~bend = ~bend.linlin(bendScale.neg, bendScale, 0, 8192*2).asInteger;
		~midiout.bend(~chan ? 0, ~bend);
		"Note: %   bend: %".format(~detunedFreq.cpsmidi.value, ~bend).postln;
	}
};
)

(
Pdef(\test, Pbind(
	\type, \midi,
	\midicmd, \noteOn, 
	
	\dur, 1,
	\legato, 1.2,
	\midiout, MIDIOut.newByName("IAC Driver", "Bus 1"),

	\scale, Scale.karjighar,
	\degree, Pseq([0, 1, 2, 3, 2, -1], inf),	
)).play;
)

You have to adjust the bendScale depending on the pitchbend range of your device. If you do something like:

\scale, Scale.chromatic,
\degree, Pseq([0, -1], inf), 
\bend, Pseq([0, 1], inf)

… you SHOULD end up with two identical notes (e.g. step down by one semitone, bend up one). I was able to adjust the bendScale until the two notes were in tune - I think 1, 2 and 12 are common defaults.

Also, this example is sending the bend event BEFORE the note on - this may not work for all hardware? - if so, you’d have to put the ~midiout.bend part in the \callback function instead of the \finish function, as this gets called AFTER the event is processed (e.g. after the MIDI note is sent).

This is cobbled together from some old code, but I think I was using this for the Elektron Analog 4 and it worked well.

apparently the bend range can be changed

The pitchbend range can be set in Settings. The default is 2 semitones.