DSPRelated.com
Forums

Guidance on Low Frequency Oscilator (LFO) implementation

Started by Jaime Andres Aranguren Cardona February 28, 2004
Jaime Andres Aranguren Cardona wrote:

   ...

Remember to keep the amplitude constant by multiplying by
1/sqrt(sin^2(x)+cos^2(x)) at each iteration. This can be computed with
no division and no root: .5[3 - sin^2(x) - cos^2(x)] Another example of
floating point making life simple!

Jerry
-- 
Engineering is the art of making what you want from things you can get.
�����������������������������������������������������������������������

Jaime Andres Aranguren Cardona wrote:

> Adrian Hey <ahey@NoSpicedHam.iee.org> wrote in message news:<c1uhki$7os$1$8302bc10@news.demon.co.uk>...
...
>>Also, I don't think you need anything fancy to calculate the sin and >>cos of such small values, just use.. >> sin(x)=x >> cos(x)=1-(x^2)/2 > > > Up to which values of x is this aproximation valid? My higher F will > be 2 Hz, equivalent to 2.85e-4 radians... I think it's still small > enough. but want to be sure.
cos(2.85e-4) = .999999959388, about 1 - 1/25,000,000. 1 is probably good enough. If not, use 1 - (2.85E-4^2)/2 = .999999959388. Home free! Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
> > > > Is there a reason that sin(n+1) = A*sin(n) + B*cos(n) > > and cos(n+1) = A*cos(n) - B*sin(n), > > > > where A = cos(delta) and B = sin(delta), both constants for any given > > frequency. A quick normalization step keeps the amplitude at unity. > > You've seen this before, but I could repeat it in detail if you need me > > to. >
Good day, I've tried this approach, plus some other suggestions posted within this thread. The "pluses" are: 1. Suggestion by Adrian Hey, quoted here: "[...]to calculate the sin and cos of such small values, just use.. sin(x)=x cos(x)=1-(x^2)/2" 2. Also by Adrian Hey: "[...] you'd be better off with 32 bit fixed point arithmetic (rather than floating point). I think you'll need 32 bits because the phase change per sample for O.O1 Hz at 44.1 KHz Fs is v.small (1.4E-6 radians according to my calculations)". So, in my SHARC assembly code: /* Local variables in DM */ .SEGMENT/DM seg_dmda; .VAR CosSine[2]; // CosSine[0] = cos(n), CosSine[1] = sin(n) .ENDSEG; Then, in an initialization routine: b0 = CosSine; i0 = CosSine; l0 = length(CosSine); m0 = 1; r0 = 0x7fffffff; dm(i0,m0) = r0; r0 = 0x00000000; dm(i0,m0) = r0; And this code is executed at a 44100 Hz: // Quadrature oscillator b0 = CosSine; l0 = length(CosSine); // Delta = sin(delta) r1 = 0xbf4; // Delta = 2*pi*0.01/44100 // Cos delta r0 = r1*r1; r0 = ashift r0 by -1, r3 = dm(i0,m0); r2 = 0x7fffffff; r0 = r2-r0, r4 = dm(i0,m0); /* R1: Sin(delta) R0: Cos(delta) R3: Cos(n) R4: Sin(n) */ r8 = r0*r3; r12 = r1*r4; r9 = r0*r4 (SSFR), r5=r8-r12; r10 = r1*r3, dm(i0,m0) = r5; r6 = r9+r10; dm(i0,m0) = r6; Thus, the cosine values are in r5 and sine values are in r6. They could be converted into floating point values with f5 = float r5; or f6 = float r6; The routine is rather fast and seems to work. I'm still verifying by using EzKit an emulator. Regards, JaaC
Jaime Andres Aranguren Cardona wrote:
>>>Question: >>> >>>Why wouldn't DDS be the simplest way to do this? Must floating point be >>>used? Is it some sort of homework problem? > > > Well, floating point is what I have in '065L (32bit fixed point too). > No, no homework problem. OK, I admit it, it seems to be.
Thanks for the reply.
> I have the article from DSP Tricks section in IEEE SP Mag, by Clay S. > Turner, titled "Recursive Discrete-Time Sinusoidal Oscillators" (what > a great article!), which I suppose will clarify many doubts to me.
Good, now I can get some idea of what you guys are talking about. I am just beginning this stuff, so I wasn't meaning to give you advice, but rather to just find out what was going on. Hope you didn't mind my butting in. I still wonder why not DDS. Is it because the 44100/2^32=0.00001027Hz frequency resolution of a 32-bit DDS isn't sufficient? I suppose a floating point calculation would give the *exact* frequency. So a DDS wouldn't be the right thing for exact frequencies, huh? Good day! -- ____________________________________ Christopher R. Carlen Principal Laser/Optical Technologist Sandia National Laboratories CA USA crcarle@sandia.gov
Jaime Andres Aranguren Cardona wrote:
> Hi, guys. > > I need your advice on the implementation of an LFO, with variable Fo > (oscillation frequency), in the range 0.01Hz <= Fo <= 2.0 Hz, sampling > at Fs = 44.1kHz. > > To be done with an ADSP-21065L in floating point (EzKit). > > Due to these ranges, a LUT (look up table) doesn't seem to be a viable > solution. >
snip Have considered function approximation?, how acurrate does it have to be? Theres an example of a DDS with sine approximation in one of the ADSP2100 app-note books, it should be good for ~14 bits I have it in C if you'd like it. -Lasse
"Chris Carlen" <crcarle@BOGUS.sandia.gov> wrote in message
news:c1vu4a01b97@enews2.newsguy.com...
> Jaime Andres Aranguren Cardona wrote: > >>>Question: > >>> > >>>Why wouldn't DDS be the simplest way to do this? Must floating point
be
> >>>used? Is it some sort of homework problem? > > > > > > Well, floating point is what I have in '065L (32bit fixed point too). > > No, no homework problem. OK, I admit it, it seems to be. > > Thanks for the reply. > > > I have the article from DSP Tricks section in IEEE SP Mag, by Clay S. > > Turner, titled "Recursive Discrete-Time Sinusoidal Oscillators" (what > > a great article!), which I suppose will clarify many doubts to me. > > Good, now I can get some idea of what you guys are talking about. I am > just beginning this stuff, so I wasn't meaning to give you advice, but > rather to just find out what was going on. Hope you didn't mind my > butting in. > > I still wonder why not DDS. Is it because the 44100/2^32=0.00001027Hz > frequency resolution of a 32-bit DDS isn't sufficient? I suppose a > floating point calculation would give the *exact* frequency. So a DDS > wouldn't be the right thing for exact frequencies, huh? > > Good day!
A DDS is a separate chip. If the hardware is already designed, there may be no DDS available. As Jerry says, "Engineering is the art of making what you want from things you can get."
I would highly recommend using extended precision (40-bit) calculation _AND_
storage for this problem.  I made an audio-frequency oscillator (as low as
20 Hz at 48kHz sample rate) and it didn't work properly until I used 40-bit
storage for the feedback elements.  (My main problem was "shrinking"
amplitude.)

I also highly recommend the paper you've found by Clay.

"Jaime Andres Aranguren Cardona" <jaime.aranguren@ieee.org> wrote in message
news:14a86f87.0402281659.a95957b@posting.google.com...
> Hi, guys. > > I need your advice on the implementation of an LFO, with variable Fo > (oscillation frequency), in the range 0.01Hz <= Fo <= 2.0 Hz, sampling > at Fs = 44.1kHz. > > To be done with an ADSP-21065L in floating point (EzKit). > > Due to these ranges, a LUT (look up table) doesn't seem to be a viable > solution. > > At this moment, I have implemented an oscillator based on the > relation: > > cos(A+B) = 2cos(A)cos(B)-cos(B-A) > > With A = 2*pi*Fo/Fs > > For initialization, or when Fo is changed, I calculate cos(B) using > 25th order McLaurin series, giving me an error of < 0.0007% for |x| <= > PI/2... But there is a little, but significative problem: the smaller > the value of Fo, the closer its cosine is to 1, and the oscillator > doesn't oscillate at all!!! Even for Fo = 1.0, I don't get the right > oscillation frequency, it's somewhat higher. > > However, I've found that for Fo >= 100 Hz. the oscillation frequency > is exactly what is expected!!!!! I tried with Fo up to 20000 Hz, with > no problemas at all. > > That makes me thing of using different approaches, coupled with my > existing oscillator design, now running at higher ("valid") Fo: > > 1. Mixing its output with another oscillator and using the relation: > > cos(A)*cos(B) = 1/2[cos(A-B)+cos(A+B)] > > Then filtering to get rid of cos(A+B), and scaling. A and B should > chosen in such a way that A-B = Fo. One drawback seems to be the fact > that, due to the fact that Fo is really small, A and B should be very > close, and I am not sure if the final effect will be to have an > oscillator at exactly Fo. > > 2. Runnimng the oscillator at a frequency N times Fo, then > downsampling by N. > > All of your opinions and suggestions are _VERY_ welcome. > > Regards, > > JaaC
"Adrian Hey" <ahey@NoSpicedHam.iee.org> wrote in message
news:c1vm9j$ooe$1$8300dec7@news.demon.co.uk...
> >> I've never generated such low frequencies though. My guess is you'd be > >> better off with 32 bit fixed point arithmetic (rather than floating > >> point). I think you'll need 32 bits because the phase change per sample > >> for O.O1 Hz at 44.1 KHz Fs is v.small (1.4E-6 radians according to my > >> calculations). > > > > Good suggestion. However, the rest of the processing is done in > > floating poin format. I think it wont be a problem to do the LFO > > generation in 32 bit, bixed point, then to use the assembler > > instructions to switch the obtained values to floating point. Or I > > could use 40 bit floating point (32 bit mantissa, 8 bit exponent) > > instead. Any opinions? > > I think 40 bit floating point should be as good as (but no better than) > 32 bit fixed point. Normal single precision floating point (24 bit > mantissa) would be worse.
I would disagree with this. With 40-bit floating point, you actually 33 bits of mantissa because of the "hidden bit". So it's slightly better than 32-bit fixed point. Also, with floating point, you will always get the full precision mantissa, even if the value is very small. With fixed point, if the signal value is substantially smaller than the maximum value, you lose precision.
Chris Carlen wrote:

> Jaime Andres Aranguren Cardona wrote: > >>>> Question: >>>> >>>> Why wouldn't DDS be the simplest way to do this? Must floating >>>> point be used? Is it some sort of homework problem? >> >> >> >> Well, floating point is what I have in '065L (32bit fixed point too). >> No, no homework problem. OK, I admit it, it seems to be. > > > Thanks for the reply. > >> I have the article from DSP Tricks section in IEEE SP Mag, by Clay S. >> Turner, titled "Recursive Discrete-Time Sinusoidal Oscillators" (what >> a great article!), which I suppose will clarify many doubts to me. > > > Good, now I can get some idea of what you guys are talking about. I am > just beginning this stuff, so I wasn't meaning to give you advice, but > rather to just find out what was going on. Hope you didn't mind my > butting in. > > I still wonder why not DDS. Is it because the 44100/2^32=0.00001027Hz > frequency resolution of a 32-bit DDS isn't sufficient? I suppose a > floating point calculation would give the *exact* frequency. So a DDS > wouldn't be the right thing for exact frequencies, huh? > > Good day!
Numbers in a computer are inevitably quantized, bignum programs notwithstanding. 32-bit floating point reserves 8 bits for the exponent and uses the other 24 for the mantissa, a trick adding an effective 25th. Trick or no, 32 bits can specify one of 2^32 states, whatever format one chooses. Since there are some disallowed floating-point states -- NAN and all that -- there are actually more fixed-point numbers that can be represented than floating point. Floating point represents a wider range of numbers, but fewer of them. Since floating-point numbers are scaled automatically, using them relieves us of the need to understand the problem well enough to scale algorithmically. Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
Jon Harris wrote:
> "Chris Carlen" <crcarle@BOGUS.sandia.gov> wrote in message > news:c1vu4a01b97@enews2.newsguy.com... > >>Jaime Andres Aranguren Cardona wrote: >> >>>>>Question: >>>>> >>>>>Why wouldn't DDS be the simplest way to do this? Must floating point > > be > >>>>>used? Is it some sort of homework problem? >>> >>> >>>Well, floating point is what I have in '065L (32bit fixed point too). >>>No, no homework problem. OK, I admit it, it seems to be. >> >>Thanks for the reply. >> >> >>>I have the article from DSP Tricks section in IEEE SP Mag, by Clay S. >>>Turner, titled "Recursive Discrete-Time Sinusoidal Oscillators" (what >>>a great article!), which I suppose will clarify many doubts to me. >> >>Good, now I can get some idea of what you guys are talking about. I am >>just beginning this stuff, so I wasn't meaning to give you advice, but >>rather to just find out what was going on. Hope you didn't mind my >>butting in. >> >>I still wonder why not DDS. Is it because the 44100/2^32=0.00001027Hz >>frequency resolution of a 32-bit DDS isn't sufficient? I suppose a >>floating point calculation would give the *exact* frequency. So a DDS >>wouldn't be the right thing for exact frequencies, huh? >> >>Good day! > > > A DDS is a separate chip. If the hardware is already designed, there may be > no DDS available. As Jerry says, "Engineering is the art of making what you > want from things you can get."
Thanks for the reply. I meant a software DDS. I have implemented a DDS in software on an AVR microcontroller, and it is not terribly difficult. I would think that the DSP could do this, instead of attempting to compute the waveforms. The only reasons I can think of not to use DDS would be that the desired phase resolution requires too lengthy a lookup table. This is probably the problem in this case. If one wanted a 16-bit signal resolution, that would warrant an 18-bit address range for the LUT. Ouch! Maybe I've answered my own question. Good day! -- ____________________________________ Christopher R. Carlen Principal Laser/Optical Technologist Sandia National Laboratories CA USA crcarle@sandia.gov