No worries! You are right that mul and add are literally just doing a (*) and a (+). The source of confusion here is what exactly is being multiplied and added. As James explained above, it has to do with what you are multiplying and adding to.
Watch in the Post window what numbers SinOsc is generating. They are between -1 and +1. We know that SinOsc.ar is generating 44100 samples per second (because of the .ar, audio rate; and assuming thatâs the sample rate of your system), but poll prints only 10 of those per second to display:
{ SinOsc.ar(freq: 1).poll }.play;
Notice that changing the freq only alters how many full cycles of up and down take place; the range of the output (-1 +1) remains the same.
Here, one full cycle every 10 seconds:
{ SinOsc.ar(freq: 1/10).poll }.play;
When you use mul and add, you are multiplying and adding that output range, it has nothing to do with the freq of the oscillator itself:
{ SinOsc.kr(freq: 1/10, mul: 1000, add: 200).poll }.play;
I changed from .ar to .kr above because didnât want this to make a loud pop going to the speakers. A huge mul in a sound-producing oscillator effectively means a huge amplitude).
The above is the same as:
{ (SinOsc.kr(freq: 1/10) * 1000 + 200).poll }.play;
âŚwhich is also the same as:
{ SinOsc.kr(freq: 1/10).range(-800, 1200).poll }.play;
Again, the point of all the above is, the mul and add have nothing to do with freq. Back to your other example with EnvGen, the reason the first one does what you expect and the second does not is that in the first you do the scaling (* and +) applied to the EnvGen, so that it is the EnvGenâs original output range 0-1 that is converted to a new range (desired audible frequencies). In the second example, by using mul and add of the SinOsc, you are effectively altering the amplitude of the SinOsc (its output), not its frequency.
Hope this helps.
Bruno