Arbitrary waveform generation

Started by R.G., March 24, 2006, 01:36:10 PM

Previous topic - Next topic

R.G.

R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

bioroids

Eramos tan pobres!

SeanCostello

Question for R.G., or anyone else who feels qualified to answer:

For these little microcontrollers, once you have yer ramp waveform being generated (or phase accumulator, whatever - it looks like a sawtooth or a ramp, so that's what I call it), is table lookup the most efficient way of converting the waveform into a sine? For the DSPs I work on, it is usually more efficient to create a sinusoidal approximation via simple waveshaping and Taylor series approximation:

- start with ramp ranging between -1 and 1.
- use fabs() to convert this into a triangle ranging between 0 and 1.
- scale and offset to get a triangle between -1 and 1.
- use Taylor series approximation to convert into a sine-ish waveform.

This works efficiently on ADI DSPs because of the ability to do single-cycle multiplications, and the assembly instruction for fabs() that also takes a single sample. However, if your microcontroller does not have a single cycle multiply, then the above technique does not seem that efficient. Has anyone here done any comparisons between different techniques of generating waveforms?

Various filter structures can also be turned into sine oscillators, and work well on fixed point DSPs, but again, not sure how they work without having a dedicated multiplier.

Sean Costello

R.G.

QuoteFor these little microcontrollers, once you have yer ramp waveform being generated ..., is table lookup the most efficient way of converting the waveform into a sine?
In general, yes. Not having a multiplier, and then not having a high precision multiplier means that the kind of stuff you do normally in a DSP is just not suitable.  However, table lookup is a whiz, and it holds the additional advantage that the waveform then becomes totally arbitrary - it's whatever you stuff into the table, or alternatively, whichever table  you look in.

I just thought I'd drop a pebble in the path for the folks who will soon be asking "but how do you vary the frequency easily?". Phase accumulation is the way it's done in arbitrary waveform generators.

There are even simpler ways. I covered some of them in my articles on digital LFOs at GEO. You can shift out a set of bits that feed resistor networks. The bits are usually something that is self addressing like a ring counter output, and the resistors encode specific values, so that the combination of a ring counter output and a suitable resistor network becomes a passive-component table lookup. An ultra-cheap sine LFO might have one of the eight pin baby PICs and one standard  CMOS shift register. I think that  you could hook suitable resistor arrays in parallel on the outputs of the SR and get all your waveforms simulataneously, although I've never seen anyone else do that.
R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

SeanCostello

Thanks for the info R.G. A few more questions:

- What sort of bit resolution do you feel is necessary for the phase accumulator for an LFO? For an audio oscillator, even 16 bits can cause audible tuning errors, to say nothing of the lower bit resolution that you find in some tone generators - some children's toys drive me crazy with their mistuned intervals. For an LFO, this seems less significant, since the frequency will be perceived as tempo, not as pitch. The difference between 200 and 220 Hz is very significant to most ears, but the difference between .2 Hz and .22 Hz is pretty subtle.

- How about linear interpolation for table lookup? This is commonly used in DSP, but it usually assumes a multiplier to do the actual interpolation. If you want 8 bits of resolution, you could use a 256 point sine table, or a 64 point quarter-sine table with some waveform manipulation, and not need interpolation. For higher bits of resolution, you need either a bigger table, or interpolation.

Thanks,

Sean

R.G.

Resolution - aye, there's the rub.

The only easy thing to do is either 8 or 16 bits, and both are doable. The only problem you'll hit up to 16 bits is that the processing time will give you an upper bound on frequency. And besides, as you note, it is an LFO, not audible pitches.

All that's shorthand for "I've done a few of these, and they sound OK, but I haven't done the math yet."  ;D

I'd try to get by without interpolation if I could.

R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

Peter Snowberg

I think it's worth noting that the AVRs have a 2 cycle hardware multiplier. :icon_wink:
Eschew paradigm obfuscation

R.G.

How about a divider, other than right shift?
R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

Peter Snowberg

Quote from: R.G. on March 26, 2006, 02:08:46 PM
How about a divider, other than right shift?

That comes in the same package as the pony.  :icon_biggrin:
Eschew paradigm obfuscation

Ardric

IMHO the beauty of using a wavetable for the LFO waveform is that we're no longer limited to simple wave shapes.  For example, the Neovibe uses an LFO and LDR's much like the Univibe because much of the mojo is said to be in the particular kind of wobbly LFO shape the bulb and LDR's contribute.  If someone was to 'sample' the resistance of the LDR and build a wavetable simulation, then couldn't we reproduce the same resulting LFO sound without all the LDR complications?  Maybe two or three tables to represent the LFO performance at slow/medium/fast speeds, with interpolation between them.

Floating point is definitely not needed for linear interpolation.  Consider Bresenham's line drawing algorithm for computer graphics.  It's simple to implement with integers, and it only needs one (integer) multiply per source table point -- the interpolated points are all addition/subtraction.  A PIC or AVR should be able to spit those out pretty darn quick.  With a little more work, magic stuff is possible... gliding LFO rate changes to tap tempo, morphing from table to table, etc.

http://en.wikipedia.org/wiki/Bresenham's_line_algorithm

I suspect a lot of circuits that use LFO's will not tolerate noise.  An 8-bit DAC could generate a lot of 'tick' sounds as it steps.  It'll need heavy low-pass filtering at the least.  Maybe a better approach would be a software delta-sigma modulator.  The simplest form would involve a single digital output from the PIC, into a crude low-pass integrator like an RC filter.  The single output bit would be diddled at as high a frequency as possible.  The cap would average this down to the output waveform, while hopefully filtering all the frequency components above that.  The nice thing about the delta-sigma approach, other than not needing a real DAC or lots of outputs, is that it pushes all the crap we don't want way up in the frequency range to the point where the simple RC is amazingly effective.  It also virtualizes the bits of resolution; we could in theory do a 24-bit DAC or better if we can just perform the adds/shifts/branches and output a bitstream at a fast enough rate.

http://en.wikipedia.org/wiki/Sigma-delta_modulation

Perhaps the chip could help with this, ie using serial interface hardware on the chip (synchronous?) to clock the bits out.

I wouldn't vary the bitclock to vary the LFO rate.  I'd use a timer interrupt driven service routine to perform the interpolation and output.  That keeps the analog low-pass parameters fixed, which is probably a big help.  If the rate is chosen to keep the CPU load at around 80-90%, the remaining CPU time is available for async jobs like handling the front panel and communications.  And the LFO output should never glitch.

Finally, I'd love to see someone use a crappy ADC in these chips to make an envelope detector, and PLL the LFO rate to that.  Maybe with a front panel phase offset control.

SeanCostello

Regarding LFO/LDR combinations such as in the Univibe, a simple wavetable will not simulate the time variation of the modulation waveform. A wavetable could capture a single speed, but as soon as the speed changes, the LFO shape will change. The lightbulb/LDR combo in the Univibe can be seen as creating a complicated, nonlinear filter, where the time constants are changing depending on whether the LFO waveform is increasing or decreasing.

Fortunately, digital effects people have to deal with similar problems in compressors and limiters. The solution is to have a first-order lowpass filter, where the coefficient switches depending on whether the input is increasing or decreasing. If you drive this by an LFO, you can design the LFO to send out a trigger whenever it changes from increasing to decreasing.

The lowpass filter can be even more powerful, in that it can convert a triangular waveform into something more closely approximating a sine. So, for simple apps, you can generate a sine approximation as so:

- Generate ramp waveform
- Use abs(), level shifting and scaling to create a triangle waveform in the desired range
- Process via lowpass filter

If the lowpass filter is fixed, the LFO amplitude will decrease with increased LFO speed (assuming that the 3db point of the lowpass filter is set lower than the LFO rate). This can be useful for phase shifters, and also simulates the effects of LDRs to a certain degree.

To truly simulate an LDR, you will probably have to do some measurements and calculations, and maybe use a higher-order nonlinear filter to perform the simulation. Some people who create high-end digital compressors have consulted quantum physicists to help map out the behavior of light-dependent resistors and certain photoelectric materials. This isn't simply marketing mojo - some digital emulations of analog gear get really in depth. Mind you, the end results of the analysis are usually mapped into some simpler technique, that approximates the desired behavior without the complexity of the theoretical equations.

If you want to create a "hypertriangular" or exponential LFO, you may wish to generate the initial modulation waveform by some variation of the above technique, perhaps with some Taylor series polynomial waveshaping to get a closer sine approximation, then put the results through a table lookup to convert the linear modulation waveform into something in log space.

A good trick to save computations: Calculate the LFO at a lower rate than the output sampling rate (say, every 16 samples, or every 32 or 128 or so).  Use a VERY simple interpolation algorithm to linearly interpolate between these points - in other words, a single addition per output sample.

Sean Costello

Transmogrifox

QuoteFinally, I'd love to see someone use a crappy ADC in these chips to make an envelope detector, and PLL the LFO rate to that.  Maybe with a front panel phase offset control.

I have an algorithm in the works for an envelope follower out of a PIC12F683.  Per my calculations, I'm totally maxing out the processor to be able to perform even an 8-bit DAC.  I'm just thinking that with adequate filtering, an 8-bit envelope follower is more than enough.

I was thinking PWM pin for DAC, then realized that the internal 8 MHz clock isn't fast enough to get 8 bits outside of the audio range.  I'm trying to avoid crystal or any external oscillators for the beauty of having an 8-pin chip that does envelope detection with few external parts.

I have come down to an algorithm that requires the "counting clock cycles" to make it work.  The DAC starts with bit 0, writes the bit for n clk cycles, then bit 1, writes the bit for 2*n clk cycles, and bit 2 is written for 4*n clk cycles....up to 8*n.

The minimum "n" base cycles is chosen by the number of instructions it takes to read a bit and write it to a pin.  As you can see, the bulk of my processing is going to happen during the write of bits 6 & 7.  uC's still can't do multiple things at once, darnit! :icon_lol:

Anyway, I'll keep y'all posted on how that experiment turns out.
trans·mog·ri·fy
tr.v. trans·mog·ri·fied, trans·mog·ri·fy·ing, trans·mog·ri·fies To change into a different shape or form, especially one that is fantastic or bizarre.