Step one, I would think, would be to investigate what the Tuning object looks like and does.
Tuning.at(\werckmeister)
-> 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.
hjh