Microcontroller Compressor

Started by grapefruit, July 08, 2006, 06:01:34 PM

Previous topic - Next topic

grapefruit

I was thinking about wether it would be worthwhile using a microcontroller to control a compressor. A search here showed up some discussion about the FMR Audio RNC.

I guess you'd full wave rectify and filter the signal and send it to the micro ADC. Then control a VCA depending upon the level getting to the dac. Attack, release and threshold could be done in software, and you should be able to get rid of any ripple by checking if the signal gets lower, then waiting for a while to check if it's gotten higer again, and only reducing the gain the signal continues to get lower.

I think the hardest part of the software would be calculating the attack time. Say we just use 8 bits of A/D. If the input gets to the level set by the threshold - at shortest attck time it should immediately reduce the level. If the attack time is longer you could have the attack time value stored in a register and use this to control a timer. Every time the timer finishes a cycle you go down 1 bit on the VCA control DAC until you get to the desired level.

I know there's a lot more to sort out on this, to work out the ratio, release etc. Suggestions are welcomed.

Stew.

davebungo

You may want to consider whether or not to convert the signal level to a log value before processing and back again prior to applying the linear gain control value. Most compressor/limiters work in this way although I don't believe it is absolutely necessary in my view.

Peter Snowberg

Since you've seen the posts on the RNC, you've probably also seen me raving about it.  :icon_biggrin:

The RNC uses a fairly basic microcontroller and achieves amazing performance with it. The big task is making a good algorithm. ;)

I think SmallBear carries THAT Corp. VCAs too. 8)
Eschew paradigm obfuscation

grapefruit

Thanks for moving the topic Peter. I didn't even realise this section existed.

I was just checking out the "That" website before. I was surprised how cheap the VCA's are.

Maybe you wouldn't have to filter the waveform. Just rectify it and then look for the peaks.
For now it might be best to think of this as an envelope follower rather than a compressor. I stumbled upon the thread "Making a generic envelope follower" and found the link to Harry Bissels design. I think doing this with a microcontroller is possible.

So - for a basic envelope follower with no attack or recovery control I'm thinking you could just get the peak value of the waveform, store this value (PEAKLEV), output it as a DC voltage, wait x amount of time - get the level again. You'd check the level a number of times and if the level is lower than PEAKLEV then store and output the new peak level.

If the input is higher than the PEAKLEV then maybe you'd update and output PEAKLEV immediately but if the peak input is lower than PEAKLEV check it a number of times. How do you make sure that at least one of your samples is done when the waveform is at the peak?

Stew.


Peter Snowberg

Quote from: grapefruit on July 08, 2006, 07:58:23 PM
I stumbled upon the thread "Making a generic envelope follower" and found the link to Harry Bissels design. I think doing this with a microcontroller is possible.

I had the same idea. A very simple micro with A/D should be able to do the job well.

Quote from: grapefruit on July 08, 2006, 07:58:23 PM
How do you make sure that at least one of your samples is done when the waveform is at the peak?

Take lots of samples. ;)

Google for "nyquist".
Eschew paradigm obfuscation

MR COFFEE

QuoteHow do you make sure that at least one of your samples is done when the waveform is at the peak?


Take lots of samples.

Or use a simple analog peak detector and zero it with your software after you digitize the value. It's probably a good idea to have more than one like in Harry Bissell's design.

The peak detection could be used by the software to change time constants like in the non-linear capacitor circuit, too.

I suspect writing the code would be pretty demanding, unless there are some great software jocks around here.

Let us know if anybody tries it. :icon_cool:

mr coffee



Bart

Transmogrifox

You can find a peak by taking a derivative--look where it's 0.  Digitally, this is easy:   x[n] - x[n-1].  Simply subract the previous sample from the current sample.  If it's  0 (or nearly 0 since your sampling resolution and speed may not allow you to nail it right on), then you have a peak.  If  (x[n] - x[n-2]) is a positive number, then it is concave down.  If negative, it's concave up.  Pick one or the other to update the peak detector register.

This can be held in a register until you find something larger, then you update.  That constitutes your peak detector.  You would need to determine how often to reset it, or you could make it "leaky" so it has a certain decay to it, or combine the two.  If it has gone a certain amount of time without being updated with a new max value, then you decrement it at a certain rate until it decays to zero or gets updated with a new max value.

You can impose attack and decay by setting up a register that tries to track with the peak detector register.  The attack/decay register will be constrained to a maximum rate of increase.  As long as it is less than the peak detector register, it will be updated periodically to increase at a set rate.  Whenever the peak detector register is less than this attack/decay tracking register, then it will be allowed to decrease at a preset maximum decay rate.  One could impose an exponential on these attack/decay rates, but a simple slew limiting approach as I described is the most easy to process in a microcontroller.
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.

MR COFFEE

Hi Trans,

Do I get you right that you mean by x(n) the instantaneous voltage of the waveform and x(n-1) the previous sample of the instantaneous voltage of the waveform ?

Seems like saving the 3 highest x values in the past howevermany ms in 3 registers, resetting the oldest one to zero every so often, and selecting the highest could implement Harry's analog approach in a uP.

Wouldn't there need to be an absolute value function as well, either in software or hardware, before you used this algorithm?

Would you say something more about your ideas for the software to do the attack and especially the decay function?

I don't know that I could pull it off, but it is a really cool idea for getting away from the too-many-chips thing in making a better than run-of-the-mill compressor or limiter.

Thanks for sharing your thoughts on this.
Bart

Transmogrifox

You have understood correctly about the x[n] thing.  I am uncertain whether you've had calculus or not, but the "difference equation" as I expressed above is a close discrete analog of the continuous time derivative.  The first derivative tells you the rate of change of a function.  When it's changing direction (such as at a peak), the first derivative is 0.

The second derivative tells you the concavity--concave up or concave down. 

You could include an absolute value function if you want, but I don't think it's necessary since the envelope of a signal is generally symmetrical enough that you wouldn't be improving performance with a peak detector by full-wave rectification.  An analog logarithmic conversion on the input of the uC and antilog (exponential) conversion of the output would help maximize the use of your 8-bit resolution.

I'll get back to the attack/decay thing later this weekend.  Once the light bulb turns on, I don't think that you'll find it to be a very hard concept to wrap your mind around.
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.

grapefruit

Quote from: Transmogrifox on October 13, 2006, 03:24:50 AM

This can be held in a register until you find something larger, then you update.  That constitutes your peak detector.  You would need to determine how often to reset it, or you could make it "leaky" so it has a certain decay to it, or combine the two.  If it has gone a certain amount of time without being updated with a new max value, then you decrement it at a certain rate until it decays to zero or gets updated with a new max value.

I was thinking about this a while ago. You'd have to wait at least 1/f the frequency of the lowest note played. Maybe twice that.

Also, if you only want to use 8 bits of resolution for the peak detector, it would be easy to full wave rectify in software. Just bias the input signal at 1/2VDD, Store ADCL as SAMPLE. Rotate right SAMPLE and fill bit 7 with bit 8 value from ADCH to get an eight bit value. If bit 9 is low then invert SAMPLE. If bit 9 is high do not invert SAMPLE. If my mind is working correctly today, then you'll have an 8 bit full wave rectified sample of the input.

I'll have to get a new STK kit. I don't think the old STK200 will program the ATtiny 15's I just got.

Stew.

Transmogrifox

Quote from: grapefruit on October 13, 2006, 08:12:38 PM
Quote from: Transmogrifox on October 13, 2006, 03:24:50 AM

This can be held in a register until you find something larger, then you update.  That constitutes your peak detector.  You would need to determine how often to reset it, or you could make it "leaky" so it has a certain decay to it, or combine the two.  If it has gone a certain amount of time without being updated with a new max value, then you decrement it at a certain rate until it decays to zero or gets updated with a new max value.

I was thinking about this a while ago. You'd have to wait at least 1/f the frequency of the lowest note played. Maybe twice that.

Also, if you only want to use 8 bits of resolution for the peak detector, it would be easy to full wave rectify in software. Just bias the input signal at 1/2VDD, Store ADCL as SAMPLE. Rotate right SAMPLE and fill bit 7 with bit 8 value from ADCH to get an eight bit value. If bit 9 is low then invert SAMPLE. If bit 9 is high do not invert SAMPLE. If my mind is working correctly today, then you'll have an 8 bit full wave rectified sample of the input.

I'll have to get a new STK kit. I don't think the old STK200 will program the ATtiny 15's I just got.

Stew.

I really think that software full-wave rectification in 8 bits is a good way to decrease performance.  If you ground reference the signal, then you have the entire 8-bit range useful for envelope detection.  If you bias to 1/2 Vcc, then you only have 1/2 of the useful resolution.  Harry Bissell's analog peak detector based envelope follower does not use full wave rectification, so why do we need to do it in software?

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.

grapefruit

Quote from: Transmogrifox on October 13, 2006, 08:36:35 PM

I really think that software full-wave rectification in 8 bits is a good way to decrease performance.  If you ground reference the signal, then you have the entire 8-bit range useful for envelope detection.  If you bias to 1/2 Vcc, then you only have 1/2 of the useful resolution.  Harry Bissell's analog peak detector based envelope follower does not use full wave rectification, so why do we need to do it in software?

[/quote]

I was thinking of with a 10 bit ADC like on the ATtiny15. If you're only using 8 bits for the peak detection you're not losing any resolution using the FWR method I described. I just thought it was a handy way to use the otherwise redundant 2 bits.

Stew.

Transmogrifox

Good point.  I'm still not sure what advantage full-wave rectification would add to a peak detection based envelope follower.
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.

grapefruit

I'm not sure if it would be an advantage but I know from looking at samples that sometimes the first half cycle peak is higher than the second half cycle, and it may be negative. This may make it more responsive. In reality it probably wouldn't make much difference.

MR COFFEE

Hi Trans and all,

The full wave rectification deal is to get two things

1) The first peak of a wave no matter the polarity

2) If I understand the math right (I took calculus a loong time ago. but didn't really get it very well), if you are looking for the largest value of a bipolar signal, doesn't that mean that the negative half of the wave is never relevant to the peak value, since any positive value is greater than any negative value?

Or am I missing something?
Bart

Transmogrifox

MR COFFEE, the use of the second derivative is for determining whether it's a positive peak or negative peak. 

Let's put the reference to calculus aside and just think of it as a series of samples.  It's simple enough to reason out intuitively without involving any more math than addition and subtraction.

At any change in direction of the signal, whether at a peak, or at a little dip or series of smaller peaks, and even a negative peak, the change from one sample to the next is going to be very small.  If you're approaching it from a software update point of view, then you look for where the change between the current sample and the previous sample is very small (like within a bit or two).  You have a "maximum hold" register that is initialized to 0.  When you find a sample that doesn't change much from the last, then you compare that sample to the "maximum hold" register value.  If it is larger, it will update.  If it's smaller, it won't.  Come to think of it, you don't even need to worry about where the peaks are.  Simply update the maximum hold register for every sample that is greater.  That will get your peaks.

That renders the whole second derivative and negative peak discussion irrelevant, really.  If you have something that's either a smaller peak, a negative peak or whatever is not a maximum positive peak, it will be ignored.  If it's only a peak detector like this, then you have the reset problem.  Harry Bissell dealt with this by instigating a round-robin reset at 3 different frequencies on 3 different peak detectors. 

In software we could do the same thing, or we could set a maximum attack and decay.  The decay will always decrement the "maximum hold" register at a set rate until it gets to 0.  This would make the "maximum hold" register always leak to 0 if the input were shut off.

The attack would modify a mirror register that would try to track the "maximum hold" register current value, but limited at a certain rate of change.  It would essentially increment the register every certain number of clock cycles until it matched the value stored in the "maximum hold" register.  If when it reaches the number stored in max hold, and then max hold begins to decrease due to the decay, then the mirror register would be a copy of the maximum hold register until it started to increase again.  This would allow you to program a set attack time and a set decay time.  You could even make the attack and decay exponential.  Probably the best way to get exponential attack and decay is to put a compressor on the input and an expander on the output.  The signal coming in would be logarithmic, but then the digital processor would impose a linear attack and decay on the envelope.  The output expander would have an exponential transfer that would make the attack and decay exponential.  This would provide optimum use of your 8-bit (or 10-bit) ADC, and would also provide a natural sounding exponential envelope attack and decay.
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.

MR COFFEE

Hi again Trans and all,

I am trying to think this through, and I hang on a couple of points.

1) without some FWR, there is no way to get really fast attack times that are accurate. If the first peak is negative, it is ignored. Not good if you want fast attack times.

2)
QuoteThe attack would modify a mirror register that would try to track the "maximum hold" register current value, but limited at a certain rate of change.  It would essentially increment the register every certain number of clock cycles until it matched the value stored in the "maximum hold" register. 

Doesn't this mean slew rate limiting instead of the traditional attack time constant? Ditto the decay time. Or does the log function take care of that?

and

3) can you do a log function in software without a fancy sophisticated uP or DSP?

This is getting really interesting.

Thanks all.
Bart

Transmogrifox

How fast of attack do you want?  Something that attacks at the rate that the first peak of the waveform strikes will sound like the equivalent of a pop.  I would argue that you wouldn't like the sound of a compressor with an attack time that fast.  Even an analog peak-detector type circuit has enough filtering to slow the attack more than that.

Not that an absolute value function is that hard...Just center the signal at 2.5V, test bit7. If it's 1, leave the byte alone, it it's 0 then complement the byte.  In Microchip assembly code the block would look like this:

BTFSS    RxReg, 7      ;Test bit 7 to determine if it's set
COMF     RxReg          ;If it's not set, complement the register
.                                ;else make no change and continue on to next instruction
.
.
where "RxReg" is the location where you store the result from the A/D conversion.

If you are attacking as quickly as the waveform deviates, you'll get some distortion on the signal since it will essentially be compressing the waveform.

Furthermore, it's unlikely that the first deviation of a signal is going to be of an amplitude that would make a difference (just my opinion). Perhaps some people do find a 10ms delay or less to have an audible effect???  I know it is argued in the pro audio world that the human ear is unable to discern a delay of less than 20ms.  I could see that a signal with a real fast attack transient could have a noisey sounding start-up if it wasn't attacked right within the first peak, but such an instrument would sound like it started with a "pop" anyway.

Look at some guitar tracks.  I think you'll see that the attack on the envelope itself is not as fast as 1/2 cycle, and the first deviation does not start at the amplitude of the envelope's highest point.

To your second question, yes, a log function can be done in a uC.  It is certainly more easily done in a full-blown DSP but it's not necessary.

My thought is that if you're using an 8-bit uC to begin with, you want to be using most of the 8 bits as much as possible.  If you run the input signal through a log amp, this flattens the envelope.  The output is then the envelope of the logged signal.  You can run this back through an exponential amp to recover the original envelope as long as your levels are calculated well enough to match the exponential as an inverse of the log.

Again, this works out great for the slew-limiting attack and decay because the exponential amp after the D/A conversion from the EF turns the attack and decay into an exponential function instead of a bland linear function.

You could generate this exponential in software, but you'd lose a good bit of signal information due to truncation.  You want to be using the most of your 8 bits on the input and output, and processing in between.   That's why a 16 bit or 21 bit processor would be a great advantage.  You'd not have to worry about it.
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.

MR COFFEE

Hi Trans,

QuoteHow fast of attack do you want?  Something that attacks at the rate that the first peak of the waveform strikes will sound like the equivalent of a pop.  I would argue that you wouldn't like the sound of a compressor with an attack time that fast.  Even an analog peak-detector type circuit has enough filtering to slow the attack more than that.

Actually I've built a number of compressors with extremely fast attack times, and if the offset is low enough, the pop is pretty minimal, and is easily rendered inaudible by allowing some of the straight signal to be mixed in with the output of the compressor, which makes the attack sound quite normal - because it is the normal attack of plucking a string with no compressor circuit in the chain - and then the compressor fades up and adds in sustain.

I'm interested in the idea of improving the processing of the control voltage controlling the decay of the compressor.

QuoteIf you are attacking as quickly as the waveform deviates, you'll get some distortion on the signal since it will essentially be compressing the waveform.

Yes, but it is inaudible because the ear cannot detect distortion that occurs for that brief a period (i.e., less than a ms}. The amplitude is also pretty low compared to the straight signal being blended in.

QuoteIf you run the input signal through a log amp, this flattens the envelope.  The output is then the envelope of the logged signal.  You can run this back through an exponential amp to recover the original envelope as long as your levels are calculated well enough to match the exponential as an inverse of the log.

Again, this works out great for the slew-limiting attack and decay because the exponential amp after the D/A conversion from the EF turns the attack and decay into an exponential function instead of a bland linear function.

You could generate this exponential in software, but you'd lose a good bit of signal information due to truncation.  You want to be using the most of your 8 bits on the input and output, and processing in between.   That's why a 16 bit or 21 bit processor would be a great advantage.

So you're suggesting a hybrid design with some analog processing ( the log and antilog functions)? Most of the ICs I'm familiar with that are designed to do that also tend to include the precision rectifier function and often include other goodies like analog rms.  And the exponential function might be unnecessary since most VCAs have a control port which responds to logged CV. Those chips tend to be pricey, but this isn't necessarily a commercial-type design, either.

With all that going on in the analog section, perhaps the uP A\D could be multiplexed to sample more than just the input signal, like the peak signal, the average, and the rms value (with a short TC), and then process the output in more complex ways to generate a tightly tracked CV that was nicely smoothed for a really natural-sounding swell.

Thanks for your input about the math part (linear slew rate on a logged signal = exponential decay rate of a linear CV signal). That makes sense when I read it, but I wasn't really sure that was how it worked before you said it. :icon_rolleyes: I have a weak grip on the math part of this business  :icon_lol:

Quotea 16 bit or 21 bit processor would be a great advantage.

It's intriguing to think in terms of less parts and doing more of the work of deriving the CV in software on the uP. Seems like some of the earlier digital FX used programmable gate array chips to dodge the high cost of DSP engines - but I expect that would take pricey design software I haven't access to  ::)  And probably be a nightmare, too...

Maybe 8 bits of resolution in the linear domain would be enough since the D\A or PCM output would be filtered by an analog post filter?

Whew, time to quit thinking about this for a while :icon_biggrin:





Bart

puretube

anyone noticed the chip mentioned here, and dug deeper into the accompanying website?  :icon_wink: