I came across this piece of code here. I’ve found some interesting ideas in this Wiki, so I come back to it from time to time to steal things or adapt them.
This line of #27 is bugging me. The variable out is a sine wave here.
I used Desmos to graph the results of applying these three trig functions to sin(x) and the resulting waveforms are really interesting.
I’m wondering:
Is there a better way to do this in SC that’s more efficient/elegant than using the sine and cosine methods?
How does this work? Or what are some resources that cover things like basic trig for DSP that might be useful? I haven’t really done any trig since high school and all I remember is what sine, cosine, and tangent are. I also know what happens if you raise them to a power and I understand their relationship to pi, but most of this math is pretty hazy for me.
How can I start to intuit the way these kinds of transformations might work? This probably is related to #2. Follow up question, how might I figure out what else I can do?
The question is more “shouldn’t you use SinOsc instead of .sin?” for example. My understanding is that trig functions are heavy, so one might use a Taylor approximation or table lookup rather than calculating sine. It was that and I think, though I’m not at my computer, something like taking the sine of a phasor ugen ranging from 0-2pi in amplitude will have more severe aliasing artifacts than the native table lookup or FSinOsc which is, what, a resonant filter?
Thanks for the explanation, that’s super helpful! I’ve often included something like a gain parameter in synthdefs recently and then used .softclip or .tanh. So what you’re saying is these are all just forms of distortion essentially and I can just use the UGens I normally would use for different flavors of distortion (.round for bitcrush, .tanh or .softclip for soft clipping, .clip for hard clipping, .fold for wave folding, etc etc) and just raise the gain to see what happens. From there of course just shaping the parameters over time to add movement?
(
p = {
var phase = Phasor.ar(0, 440 * SampleDur.ir, 0, 2pi);
var sin = phase.sin;
var sinosc = SinOsc.ar(0, phase);
sin absdif: sinosc
}.plot(duration: 1);
)
p.plots[0].value.maxItem // 4.3213367462158e-07
p.plots[0].value.maxItem.ampdb // -127.28763778729 dB
Not really aliasing but rather, inaccuracies in the sample values raise the noise floor. However, this is quite near the bottom end of the ~140dB dynamic range of 24 bits so the probability of it being detectable to the ear is rather low. (The noise floor of a 16-bit CD quality recording is louder than this.)
But I don’t think SinOsc.ar(freq) and SinOsc.ar(0, Phasor.ar(0, freq * SampleDur.ir, 0, 2pi)) are analogous in the way they’re implemented. I noticed this a few weeks ago.
(
{
var a = SinOsc.ar(400);
var b = SinOsc.ar(0, Phasor.ar(0, 400 * SampleDur.ir * 2pi, 0, 2pi));
var c = a absdif: b;
RunningMax.ar(c).poll; //this should work since it's sampling absdif at audio rate, right?
[a,b,c]
}.plot;
)
You’re right that I did mess up the formula – it should have been Phasor.ar(0, freq * SampleDur.ir, 0, 1) * 2pi or Phasor.ar(0, freq * SampleDur.ir * 2pi, 0, 2pi).
However, the initial question was about differences between sin() and SinOsc, and it is valid to compare those with equivalent phase inputs, at any frequency. So my example looks like I meant 400 Hz while it doesn’t produce 400 Hz (true), but it does correctly report differences between the two methods of calculating the sine of the same phase.
Thanks James. The comparison results were a lot more significant when I tried it again (after multiplying frequency by 2pi), so I guess now it’s more a matter of considering trade off between FSinOsc (amplitude deviations), SinOsc (usually what I end up using and of course that’s the intent), Phasor, .sin, etc.
I feel like this is a good question to ask when you’re doing something with additive synthesis and a ton of sine waves, which I’m not doing.
I tend to obsess about efficiency and these questions I just find interesting.
That is, assuming C’s sin() function is more accurate than SinOsc’s wavetable lookup, the noise introduced by SinOsc is ~30 dB quieter than that of a 16-bit audio release. It’s negligible – really, it’s nothing to worry about.