Hello,

When I was playing with fb_fcomb(), I accidentally noticed this
trigonometric identity (thanks to maxima):

        cos(x)*sin(n*x) = (sin((n+1)*x)+sin((n-1)*x))/2

and it gave me idea to write the following:

        harmonics(vs, c0,s0)
                = c0*vn(0),s0*vn(0), 1,c0, 0,s0
                : seq(n, outputs(vs)-1, add(vn(n+1)))
                : _,_, !,!, !,!
        with {
                vn(n) = ba.take(n+1, vs);

                add(vn, co,so, cn_2,cn_1, sn_2,sn_1) =
                        co+cn*vn, so+sn*vn, cn_1,cn, sn_1,sn
                with {
                        cn = 2*c0*cn_1 - cn_2;
                        sn = 2*c0*sn_1 - sn_2;
                };
        };

What does it do. For example, for any x

        cos(x), sin(x) : harmonics((10,20,30))

outputs

        10*cos(x) + 20*cos(2*x) + 30*cos(3*x),
        10*sin(x) + 20*sin(2*x) + 30*sin(3*x);

(of course, modulo floating point issues)

IOW,

        qo(f) = os.oscrq(f);    // or any other complex oscillator
        process = qo(f) : harmonics((10,20,30));

acts as

        // pseuodo code, x * qo(...) won't compile
        process = 10*qo(f) + 20*qo(2*f) + 30*qo(3*f);

but it is more simple/cheap.

-------------------------------------------------------------------------------
Note that it does not use the

        [ c0  -s0 ]
        [ s0   c0 ]

rotation matrix, and this means that

        - we save one multiplication in the calculation of each harmonic

        - more importantly, the calculations of cn and sn do not depend
          on each other.

          So if you only need the "sines" part you can do

                qo : harmonics(volumes_list) : !,_;

          and compiler will discard the half of the calculations.

-------------------------------------------------------------------------------
Questions:

        - does it make sense to add this function to oscillators.lib ?

        - is it a known method? I am just curious.

-------------------------------------------------------------------------------
Just in case... perhaps the more "generic" version makes more sense:

        harmonics_parallel(N, c0,s0)
                = c0,s0, 1,c0, 0,s0
                : seq(n, N-1, (si.bus(2*(n+1)),add))
                : si.bus(2*N), !,!, !,!
        with {
                add(cn_2,cn_1, sn_2,sn_1) =
                        cn,sn, cn_1,cn, sn_1,sn
                with {
                        cn = 2*c0*cn_1 - cn_2;
                        sn = 2*c0*sn_1 - sn_2;
                };
        };

so that

        qo(f) : harmonics_parallel(3);

outputs

        qo(f), qo(2*f), qo(3*f);

Oleg.



_______________________________________________
Faudiostream-users mailing list
Faudiostream-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-users

Reply via email to