OK, since you got my curiosity up, I concocted a little test.
I started with a gapped sawtooth spectrum, every third harmonic. I figured that would have enough empty space in the spectrum to see aliasing in the upper extreme range.
I played around with MouseX for a while, and found a frequency that had a good spectrum with MultiWtOsc:
Then tried the same frequency with OscOS (without oversampling, only its on-the-fly mipmapping):
And with 4x oversampling:
Now, this frequency was empirically found to show ideal behavior in MultiWtOsc. So I looked for another frequency where some aliasing is visible = 1305.52 Hz.
So MultiWtOsc doesn’t block all aliasing… but neither does OscOS. (I won’t post graphs for OscOS, but they’re very similar to the others.)
MultiWtOsc mipmaps more aggressively – it cuts off more high frequencies than it needs to. This has the disadvantage of losing a bit of brilliance in the top end (probably – my hearing is pretty well gone above, oh, 12 kHz by now, not bad for my age but still), but the advantage of completely removing aliasing in some frequency ranges and mostly removing it in others. OscOS’s sound might be more consistent, but that consistency seems to include, ironically, more aliasing. (However OscOS should sound better at very, very high frequencies – I limited my tests to <= 6000 Hz; above that, I saw some weird behavior with my mipmapping alone.)
CPU:
- Baseline (only freq analyzer): 5-6%
- MultiWtOsc: 7-8%
- OscOS (no OS): 14-16%
- OscOS (4x OS): 37-40%
This doesn’t mean that two OscOS’s would hit 80% – that would probably cause the machine to raise the CPU clock speed – but it does show the magnitude of the CPU hit, and why I decided to stick with MultiWtOsc for my purposes.
Also curiosity up
and I’d have to agree that, of these three UGens, SingleOscOS looks a lot better than OscOS, and CPU use isn’t heavy. But I think the two extra harmonics in this graph are harmonic distortion, not part of the original spectrum.
2876 Hz:
And 1305.52 Hz is icky for all 3 UGens:
So as for the statement that SingleOscOS would be “way” better – I just don’t see that in the graphs. When sweeping the frequency, SingleOscOS looks more consistent and smoother than MultiWtOsc, but I don’t see a stark contrast between “one looks great” and “the other looks awful.” I’d say “one looks good” and “mine looks slightly less good.” So they are different beasts and users should choose according to their needs.
hjh
// make a wavetable with every third harmonic
// a 2048-sample cycle can go up to 1024 cycles/window; stop a bit short of that
s.boot;
(
w = Signal.sineFill(2048, Array.fill(1020, { |i|
if(i % 3 == 0) { (i+1).reciprocal } { 0 }
}));
)
// optional, see freq analysis
// w.fft(Signal.newClear(w.size), Signal.fftCosTable(w.size)).rho[0 .. (w.size div: 2)].plot
p = WavetablePrep(wtSize: w.size, numMaps: 8, ratio: 2, filter: \brickwall);
p.readStream(SoundFileStream(w));
m = SoundFileStream.new;
p.writeStream(m);
b = Buffer.sendCollection(s, m.collection, 1);
// 6000 Hz = midinote 114.232644 or F#, 4 octaves above mid C
// also try 1305.52 = dodgy; 2876 = nice
(
a = {
var freq = 1305.52; // MouseX.kr(50, 6000, 1);
var sig = MultiWtOsc.ar(freq, wtPos: 0,
bufnum: b,
wtSize: 2048,
numTables: 8,
ratio: 2,
interpolation: 4
);
(sig * 0.04).dup
}.play;
)
a.free;
// OscOS dynamic mipmapping only
(
a = {
var freq = 1305.52; // MouseX.kr(50, 6000, 1);
var phase = Phasor.ar(0, freq * SampleDur.ir, 0, 1);
var sig = OscOS.ar(b, phase, buf_divs: 8, buf_loc: 0);
(sig * 0.08).dup
}.play;
)
a.free;
// OscOS mipmap + 4x oversampling
(
a = {
var freq = 2876; // MouseX.kr(50, 6000, 1);
var phase = Phasor.ar(0, freq * SampleDur.ir, 0, 1);
var sig = OscOS.ar(b, phase, buf_divs: 8, buf_loc: 0, oversample: 4);
(sig * 0.08).dup
}.play;
)
a.free;
(
a = {
var freq = MouseX.kr(50, 6000, 1);
var phase = Phasor.ar(0, freq * SampleDur.ir, 0, 1);
var sig = SingleOscOS.ar(b, phase, 8, 0, oversample: 0);
(sig * 0.08).dup
}.play;
)
a.free;