MIDI and Tuning (microtuning)

Has anyone translated incoming MIDI notes to microtonal values? All the documentation on Tuning and Scales in SC use Pbind, which i am not using.

I receive MIDI from an external sequencer, like this:

 MIDIFunc.noteOn({|vel, midinote|
    ~synths[midinote] = Synth(\tx81z, args:[kfreq:midinote.midicps, vel:vel]);

Ideally, i want to load a tuning and make the midinote.midicps adhere to that new tuning before it updates the “freq” parameter in the synth. But i can’t wrap my head around it.

Thanks for all help.

As I understand it, midi notes have a defined meaning in the standard tuning – that’s what .midicps does. If you want to go to another tuning, or even microtonal, you’d first have to specify the new mapping – which frequency you’d like the midinote to go to instead. Once you’ve defined that, say in a dictionary, it’ll be easy to convert incoming midinotes to freqs for your synth arg.

Perhaps I’m misunderstanding …





I finally managed to figure this out! If everyone else is wondering, here is how:

> (
> var scale;
> scale = Scale.chromatic;
> scale.tuning_(\reinhard);
> ~synths = Array.fill(128, nil);
> MIDIFunc.noteOn({|vel, midinote|
> 	~synths[midinote] = Synth(\tx81z, args:[kfreq:midinote.keyToDegree(scale, 12).degreeToKey(scale).midicps,
> 		vel:vel, algorithm:1]);
> });
> MIDIFunc.noteOff({|vel, midinote|
>     ~synths[midinote].set(\gate, 0);
> });
> )

the important bit is:

scale = Scale.chromatic;
kfreq:midinote.keyToDegree(scale, 12).degreeToKey(scale).midicps

where “kfreq” is the frequency argument of the synth.


1 Like

Step one, I would think, would be to investigate what the Tuning object looks like and does.


-> Tuning([ 0, 0.92, 1.93, 2.94, 3.915, 4.98, 5.9, 6.965, 7.93, 8.895, 9.96, 10.935 ], 2, "Werckmeister III")

That looks like C = normal, C# = 8 cents flat, D = 7 cents flat and so on. So if you look up the chromatic note value in this array, then you know how much to deviate from equal temperament.

In other words, these are midicps values.

That leaves octave transposition. Given a note number, what is the octave? Well… divide by the number of semitones in the octave and chop off any fraction – ‘div’ is integer division, useful here. Then multiply that back by the number of semitones. EDIT: trunc may be quicker.

f = { |midinote, tuning|
	tuning.wrapAt(midinote)  // look up, without considering octave
	+ midinote.trunc(tuning.stepsPerOctave)

f.(62, Tuning.at(\werckmeister))

-> 61.93

And then you can use this with midicps.

EDIT: I forgot about scale root. You can subtract the root before looking up the tuning, and then add the root back:

f = { |midinote, root(0), tuning|
	midinote = midinote - root;
	tuning.wrapAt(midinote)  // look up, without considering octave
	+ midinote.trunc(tuning.stepsPerOctave)
	+ root

f.(64, 2, Tuning.at(\werckmeister))

Tuning has other variables – this function doesn’t account for an octave ratio != 2 – but if it’s not relevant to your use case then there’s no reason to overcomplicate.