three state form of circular osc?

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

ye old circular osc..

state1 -= state2 * rate
state2 += state1 * rate

can a spherical oscillator be implemented in a similar manner? :hyper:
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

xoxos wrote:ye old circular osc..

state1 -= state2 * rate
state2 += state1 * rate

can a spherical oscillator be implemented in a similar manner? :hyper:
To begin with, this is not a circle, but an ellipse (which leads to the oscillator's instability, especially in modulations). Otherwise, I'm not sure which 3D trajectory do you have in mind? Sphere has much more possibilities than a circle :-P

Post

Can't you simply use unit quaternions / versors?

Post

Z1202 wrote:I'm not sure which 3D trajectory do you have in mind?
yes, it looks like there's no getting around that it would have to have that. i only got as far as :hyper:

but i'm glad i could get to the volatile state of :hyper: without an angle.
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

You could rotate the circle's normal around the sphere.

Post

Just curious, how do you use this recursion?
I set state2 at 0.1 and a rate of 0.5, and it looks like it is forming sin and cos, but it has some problems.

Post

you also want to know about
float leg = c * c + s * s; // once every block
if (leg) {leg = sqrt(leg); c /= leg; s /= leg;}

noted under 'fast sine osc' here and elsewhere http://www.xoxos.net/sem/dsp2public.pdf
(i picked it up here from mystran, you see it around)
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

The error looks like ring modulation, 'leg' fixes it? Do you take the output of s2 before calculating it?

Post

xoxos wrote:you also want to know about
float leg = c * c + s * s; // once every block
if (leg) {leg = sqrt(leg); c /= leg; s /= leg;}

noted under 'fast sine osc' here and elsewhere http://www.xoxos.net/sem/dsp2public.pdf
(i picked it up here from mystran, you see it around)
My guess is that (even though there are some specialized fast sqrt instructions in SIMD) it's still more efficient to use a Taylor expansion of 1/sqrt around 1.

Post

camsr wrote:Just curious, how do you use this recursion?
I set state2 at 0.1 and a rate of 0.5, and it looks like it is forming sin and cos, but it has some problems.
It is not exactly sin and cos, so it gives you an ellipse rather than a circle. Which is okay, as far as sine generation goes, but you don't get a correct pair of sin and cos (for that you should rather use the complex exponent recursion: w[n+1]=w[n]*exp(i*deltaPhi) ). The ellipse is also changing its shape with frequency, which leads to strong amplitude drift and possible explosions when modulated.

Post

Are you sure? I have implemented a test program and with lower rate, I see less divergence from the unit circle.

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>

int main () {

//
//state1 -= state2 * rate
//state2 += state1 * rate
//state 2 lags state 1 by a sample, so buffer s2s is required

double s1, s2, r, d, s2s;
double s1max, s2max, dmax = 0.0;
int c, cloc1, cloc2, cloc3 = 0;

s1 = 1.0;
s2 = 0.0;
r = 0.001;
d = 0.0;
s2s = 0.0;
dmax = 1.0;

for (c = 0; c < 1600; c++)
{

s1 -= s2s * r;
s2 = s2s;
s2s += s1 * r;

d = s1*s1 + s2*s2;
printf("%d: %1.6f\t%d: %1.6f\t%d: %1.6f\n", c, s1, c, s2, c, d);

if (fabs(s1) > fabs(s1max))
{ s1max = s1; cloc1 = c; }
if (fabs(s2) > fabs(s2max))
{ s2max = s2; cloc2 = c; }
if (d < dmax)
{ dmax = d; cloc3 = c; }

}

printf("Max s1 @ %d: %1.16f\t Max s2 @ %d: %1.16f\tMax d @ %d: %f\n", cloc1, s1max, cloc2, s2max, cloc3, dmax);
system("pause");

return 0;
}
The output is 3 columns, the first s1, the second buffered s2, the third divergence.

Post

//state1 -= state2 * rate
//state2 += state1 * rate

ok that's basically...

(x,y) = (x,y) + d*(-y,x)

(-y,x) is a vector 90 degrees anti-clockwise to (x,y). So draw a point from (0,0) to (x,y) then draw a normal from (x,y) anti-clockwise, of length d. That's what you do each iteration. The larger 'd' is the greater the next point will be away from the unit circle. It'll be an ever growing spiral AFAIK.

Essentially the error accumulated each step is proportional to 'd', lower speed == less error.
Chris Jones
www.sonigen.com

Post

The algo is known as the magic circle. It yields stable sine and nearly cosine (nearly because it is delayed by half a sample) as long as you don't change frequency. The trick is that updating of the states is staggered, so it won't spiral. As soon as you modulate, however, amplitudes start to drift, the more so the higher the frequency. As Vadim points out, the coupled form (non-staggered updating) avoids that (but has other issues).
Clay Turner has a nice paper on digital oscillators.

Post

Ah ok, thats a new one to me. So it's really stable? I mean indefinately? Not just *more* stable than the non staggered form?
Chris Jones
www.sonigen.com

Post

Yes, according to Dattorro, the magic circle "is hyperstable because the pole radii are exactly 1 (even when ε is quantized)." This is in contrast to the coupled form.

Post Reply

Return to “DSP and Plugin Development”