Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
119 lines (97 sloc) 2.46 KB
// note scaling table
// 12-tone equal temperament, with microtunes
// 10-bit linear input gives 7 microtunes, costs 4k
n = 2**10;
// 12-bit linear input gives 31 microtunes, costs 16k
// n = 2**12;
i = Array.series(n);
// let's use 128 semitones.
// so the full range is 10 octaves + 8 semitones.
// number of semitones
~nsemi = 128;
// microtuned steps per semitone
~nmicro = n / ~nsemi;
// semitone tempered ratio
~root_semi = 2 ** (1/12);
// microtune tempered ratio
~root_micro = ~root_semi ** (1/~nmicro);
// semitone ratios of fundamental
~fsemi = ~nsemi.collect({
|j| (2 ** ( j / 12).floor)
* (~root_semi ** (j % 12))
});
// fill in semitones on main table
// float ratios
f = i.collect({ |j|
if( (j % ~nmicro) == 0, {
~fsemi[ (j / ~nmicro).floor ]
}, {
nil
});
});
// fill in microtunings
{
var fSemId = 0;
// 32nd root of ratio between semitones
~nsemi.do({ arg iSem;
~nmicro.do({
arg iMic;
if (iMic != 0, {
f[fSemId + iMic] =
f[fSemId] * (~root_micro ** iMic)
});
});
fSemId = fSemId + ~nmicro;
});
}.value;
// base frequency: concert middle c, minus 5 octaves (~8hz !)
~base = 60.midicps / 32;
~base.postln;
// multiply float ratio table
f = f * ~base;
//f.plot;
f.do({ |x, j|
(" " ++ j ++ " : " ++ x ++ " hz : " ++ x.cpsmidi).post;
if( (x.cpsmidi - (x.cpsmidi.floor )) < 0.0001, {
" <<<<---------------------------"
}, { ""
}).postln;
});
// convert to 16.16.
// fortunately, it doesn't cost much to use the 16.16 representation directly in the DSP.
// so i think we can get away with only one table.
v = f.collect({ |x, i|
var xint, xfr, y;
xint = x.floor;
xfr = x - xint;
xint = xint.asInteger;
y = (xint << 16) | (0xffff & ((xfr * 0x10000).floor.asInteger));
});
v.do({ arg y; y.asHexString.postln; });
////// output to files
/// binary, big endian
// value
~vf = File.open(File.getcwd ++ "/scaler_note_12tet_val.dat", "wb");
// write size
~vf.putInt32(n);
// write data
v.do({ |x| ~vf.putInt32(x) });
~vf.close;
// use the same 16.16 values for SVF corner frequency representation.
// new table for corresponding coefficients.
// 2x oversampled
~sr = 96000.0;
~cf = f.collect({ |fc|
2.0 * sin(pi * min(0.25, fc / ~sr));
});
//~cf.do({ |x| x.postln; });
//~cf.plot;
~cfv = ~cf.collect({ |x| (x * 0x7fffffff).asInteger });
~cfv.do({ |x| x.postln; });
// value
~cfvf = File.open(File.getcwd ++ "/scaler_svf_fc_val.dat", "wb");
// write size
~cfvf.putInt32(n);
// write data
~cfv.do({ |x| ~cfvf.putInt32(x) });
~cfvf.close;