Arduino LFO: generate waveform or use table?

Started by earthtonesaudio, October 15, 2012, 02:59:39 PM

Previous topic - Next topic

earthtonesaudio

I am starting an Arduino LFO project.  I hope to use the ATmega 328 to generate the waveform and some other stuff (maybe some limited audio processing).

At this point I am synthesizing the waveform but I have seen many other projects use look-up tables.  Is a LUT faster?  What are the other tradeoffs involved?

composition4

LUT = faster than calculating a function, but takes up a lot more room... depends on whether it's more important to save cycles or memory in your project

earthtonesaudio


cloudscapes

I use tables for my LFOs

the nice thing about using a table is you use the same code for any of your LFO types. sine costs the same in cycles as triangle, square, ramp, etc. you just have to swap your data table for each one. if you had to devise algorythms for each type, you'd have to compensate in clock cycles for each one.
~~~~~~~~~~~~~~~~~~~~~~
{DIY blog}
{www.dronecloud.org}

g_u_e_s_t

i use lookup tables as well
i tend to use 1k sample tables
which is a bit excessive
but thats still a small percentage of 32k in an arduino
and it is much much faster

if you do your table boundaries on a factor of 2 index
you can just do &0x03ff (for 1024 for example)
which is faster than checking for the boundary each time

the only times that a lookup table wont be faster than computation
is for ramp waves or square waves

harmless

I've only made a tremolo, but just calculating the waveform rather than doing a LUT worked fine for me.  I don't have a scope to verify or anything, but everything sounded nice and smooth.

I captured the ticks on startup and then every cycle did (currentticks - start) mod period to get the offset into the current wave and then just had functions to calculate the amplitude for each of my wave shapes.  Sine/cos are the only computationally scary ones but they ran just fine for me.  I suppose if you were really worried about that you could approximate sine with a few linear sections.

Seljer

Quote from: harmless on October 24, 2012, 04:16:30 PM
I've only made a tremolo, but just calculating the waveform rather than doing a LUT worked fine for me.  I don't have a scope to verify or anything, but everything sounded nice and smooth.

I captured the ticks on startup and then every cycle did (currentticks - start) mod period to get the offset into the current wave and then just had functions to calculate the amplitude for each of my wave shapes.  Sine/cos are the only computationally scary ones but they ran just fine for me.  I suppose if you were really worried about that you could approximate sine with a few linear sections.

I have no idea what the standard C function does, but if you can be bothered to do the math, you can get a trig function down to reasonably accuracy (within the range of 10^-4) by replacing with it third order polynomial approximation (which can be computed with three or four multiplaction operations and some additions and other checking).

However, the lookup table is probably the more flexible option, espescially when you want to add various other waveshapes

cloudscapes

using tables you could also devise blending between them as well. this would be really hard to do using algorythms, but a piece of cake with tables
~~~~~~~~~~~~~~~~~~~~~~
{DIY blog}
{www.dronecloud.org}

MoltenVoltage

With tables you will have noticeable stairsteps at long LFO times.  With calculating, you will hit a point where they chip can't generate the waveform fast enough without getting skewed.

Assuming the chip is fast enough, I strongly recommend calculating.  If the chip has built in oversampling/interpolation on the analog output, like the dsPIC in our Tru-Foot LFO, then calculating will result in a smooth waveform - no need to filter the output.
MoltenVoltage.com for PedalSync audio control chips - make programmable and MIDI-controlled analog pedals!

Seljer

Quote from: MoltenVoltage on October 25, 2012, 02:40:46 AM
With tables you will have noticeable stairsteps at long LFO times.  With calculating, you will hit a point where they chip can't generate the waveform fast enough without getting skewed.

Assuming the chip is fast enough, I strongly recommend calculating.  If the chip has built in oversampling/interpolation on the analog output, like the dsPIC in our Tru-Foot LFO, then calculating will result in a smooth waveform - no need to filter the output.

You can interpolate tables with a simple linear interpolation which doesn't need much math at all

cloudscapes

Quote from: Seljer on October 25, 2012, 02:47:26 AM
You can interpolate tables with a simple linear interpolation which doesn't need much math at all

Yup, that's exactly what I do. My tables are 256 samples "long", then I linear interpolate times 20 at longer frequencies. easy enough.
~~~~~~~~~~~~~~~~~~~~~~
{DIY blog}
{www.dronecloud.org}

earthtonesaudio

A table with linear interpolation sounds to me like a nice hybrid approach.

harmless

Linear interpolation is exactly the calculation you do to just calculate the wave form in the first place :)

Ok fine, so triangle has one if statement to see if you're rising or falling, and sine has n if statements (4 - 8 ish) depending on how many lines you use to approximate a curve.

Tables are fine, but linear interpolation of tables has nearly the same overhead as the calc itself.

Jazznoise

LUT tables don't have to be the full waveform, either. I generated a sine wave form a half a sine LUT with no issues, just read it forwards and backwards. This works better for some waveforms than others, obviously.

I was using flowcode as I'm not a programmer, and my 16f88's were not very happy about what I was trying to do. I had meant to try generating waveforms from a 90 degrees of a cycle: Read table, read table backwards, read table but subtract from max value( say 1), and then invert that.

What are people here using to program their PIC's, and what's a good resource for it?

Also, I had a freind play a note on the Saxaphone and I generated a wavetable from a cycle of that. I think I've the file, but I've no longer access to Matlab. If I can find the LUT or something else with a wavread function. Might be fun to do some of guitar, piano, trumpet, maybe a pair of 5ths etc. etc.

What would two notes a semitone apart sound like as an LFO?  :icon_eek:
Expressway To Yr Null

cpm

arduino library implement complex functions like "sin", and has datatypes and operations on floating point numbers. But you must take into account they are heavy computational operations, and take a lot of instruction cycles just to perform one operation, and during those cycles your program flow is locked. Worse is if you place that instructions inside an interrupt, because then you cannot do anything else, at all.

And then you have PWM resolution. If its set up for 256 steps there is no point in having a 1k table...

ElectricDruid

Another vote from me for LUT+linear interp.

If you don't use the linear interp, waveforms with steep rises can have steps in (as MoltenVoltage mentioned) since next-door LUT values will differ significantly, and you'll hear the jump for very low frequencies. Linear interp turns that step into a smooth slope, which you'll never hear.

Quote from: harmless on October 29, 2012, 05:24:11 PM
Linear interpolation is exactly the calculation you do to just calculate the wave form in the first place :)
Ok fine, so triangle has one if statement to see if you're rising or falling, and sine has n if statements (4 - 8 ish) depending on how many lines you use to approximate a curve.
Tables are fine, but linear interpolation of tables has nearly the same overhead as the calc itself.

I don't agree. That might be true for triangles, but not for the general case. Someone mentioned using a Taylor approximation for a sine wave which would take much more work than a simple linear interp. Other non-straight line waveforms would be next to impossible, whereas as others have pointed out, a LUT+interp can do any arbitrary waveshape to the same degree of quality.

HTH,
Tom

potul

Hi,

Another potential approach to save space would be temporary tables. You calculate the table values once and populate a temporary table you use until you need a new shape.

It can be feasible depending on your needs in terms of timing and when the shape change occurs.


earthtonesaudio

#17
From what people are saying it seems that interpolation is most useful for very slow waveforms.  Conversely it is less beneficial for fast waveforms, and starts to become a drag on the processor anyway.  

So why not use interp only for speeds below some threshold?

One other thing... You could use some external circuitry and another pin (maybe with just one pin if you're clever) to generate the other half of a full wave rectified sine (or any wave), so you can in theory generate a full sine from just a quarter period.