Pretty fun!  This looks closely related Andy Moorer's technique:

@ARTICLE{MoorerDSF75,
        AUTHOR = "James A. Moorer",
        TITLE = "The Synthesis of Complex Audio Spectra by Means of
                Discrete Summation Formulae",
        JOURNAL = JAES,
        VOLUME = 24,
        PAGES = {717--727},
        MONTH = dec,
        NOTE = "Also available as CCRMA Report no.
\htmladdnormallink{STAN-M-5}{https://ccrma.stanford.edu/STANM/stanms/stanm5/
}",
        YEAR = 1975
}

I think there's even a patent.

I vote in favor of the addition provided its well documented in its
comments -> MarkDown extraction.

Cheers,
Julius

On Sun, Aug 20, 2023 at 3:55 PM Oleg Nesterov <o...@redhat.com> wrote:

> 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.
>
>

-- 
"Anything that can be automated should optionally be"
_______________________________________________
Faudiostream-users mailing list
Faudiostream-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-users

Reply via email to