[chuck-dev] On SinOsc, Wavetables, Unit Circles, etc.

Joel Matthys jwmatthys at gmail.com
Fri Sep 18 15:56:10 EDT 2015


Thanks everyone for chiming in on this interesting topic!

I had suspected what Perry said: that ChucK wasn't designed with 
"particular regard for efficiencies." But I had no idea that Math.sin 
isn't as expensive as it used to be. I had always taken it as gospel 
that trig calls were to be avoided! Thanks for the info about resources 
on optimal table size, depth, etc.

It sounds to me like SinOsc isn't as inefficient as I had thought, but 
I'm still interested in the idea of a customizable Wavetable instrument. 
I hadn't thought of SndBuf, but I guess with a few new methods of 
pulling in the table and maybe a different interpolation method (bearing 
in mind Nat's warning about efficiency!) I think it could be useful.

Joel

On 09/18/2015 12:56 PM, Perry Cook wrote:
> Hey all,
>
> Chiming in on the various Sine-related topics here.  SinOsc was designed like
> most of ChucK, to do things from the definition, without particular regard for
> efficiencies.  In fact, a native Math.sin(BLAH) call isn’t that hideous.  It used
> to be in the olden days, and we avoided it like the plague.  The Motorola DSP
> 56000 had a built in quarter-wave of sine in ROM.  (It also had an 8-bit muLaw
> decoding table built in as well).  Many papers (Snell, Others) were written about
> the optimal length, bit-depth, etc of a sine table given different types of interpolation.
> Yamaha chips stored sine quads in both linear (for addition) and log (for
> multiplication) ROM, or hard-coded into gates for the absolute minimum expense.
>
> Wavetables:
> Indeed, SndBuf is ChucK’s built-in wavetable (in .loop mode).  And, it could be a
> little cheaper, and it has built-in linear interpolation.  If you want less distortion, just
> make your table longer.  The “table” here is a .wav file you create and load.
> All you need add is an accessing function to set rate as a function of frequency.
> And you could also add FM, PM, and other .sync-like functions as well.  By this
> time, it might be worth comparing to SinOsc efficiency for FM and other audio-
> rate modulation tho.  I just did a quick check and find SndBuf to be about equal
> to SinOsc (the number I can run before audio starts breaking up, just over 400).
> See code below.
>
> Note also that there are some other wavetable-like UGens already in the GenX
> family in ChucK.  I don’t know about the relative efficiency of those, and I do
> know that that you need to drive (some of) them with a Phasor.  So again, it
> might not end up being significantly cheap.
>
> On unit-circle sine generation:  Spencer has already given us a great ChuGen
> called MagicSine, that does the rotation-based sine generation using only
> a couple of multiplies and adds.  It’s most efficient if you’re not changing
> frequency rapidly.
>
> Julius and I also did a “waveguide resonator” oscillator (similar to Magic
> Sine), but it also had built in exponential envelope (phasor that spins outward
> or inward), and allowed for modulation of the parameters for FM-like
> wave distortion.  Not particularly efficient if you just want a sine wave.
> I have a ChuGen for that too, but never released it.
>
> So the topic "many ways to skin a sine" is still active today!!
>
> My comparison codes (in terminal, miniAudicle may vary, also Audio BUFSIZE might help):
>
> /* SinOscCompare.ck  ***************************************/
> SinOsc s[1000];
> Gain outMix => dac;
>
> for (int i; i < 4000; i++)  {
>     if (i%100 == 0) <<< "Sines", i+1 >>>;  // this could be costing us some
>     s[i] => outMix;
>     Math.random2f(100,3000) => s[i].freq;   // as would this
>     1.0/(i+1.0) => outMix.gain;                 // and this
>     10*ms => now;				// but if those dominated, we’d probably hear 100 Hz distortion
> }
>
> vs.
>
> /* SndBufCompare.ck   ***************************************/
> SndBuf s[1000];
> Gain outMix => dac;
>
> for (int i; i < 4000; i++)  {
>     if (i%100 == 0) <<< "SndBufs", i+1 >>>;  // this could be costing us some
>     "special:dope" => s[i].read;                     // maybe this too, but cacheing should help
>     1 => s[i].loop;
>     s[i] => outMix;
>     Math.random2f(0.2,5.0) => s[i].rate;      // as would this
>     1.0/(i+1.0) => outMix.gain;			// and this
>     10*ms => now;				// but if those dominated, we’d probably hear 100 Hz distortion
> }
>
>
>
> _______________________________________________
> chuck-dev mailing list
> chuck-dev at lists.cs.princeton.edu
> https://lists.cs.princeton.edu/mailman/listinfo/chuck-dev



More information about the chuck-dev mailing list