Hi guys, I'm pretty new to DSP. I've been implementing various effects in Matlab, mostly using code from the DAFX book. I'm working on compressors at the moment, actually trying to get one working in realtime in an Audio Unit. I'm just having some trouble visualising how the attack and release envelopes work. To keep things simple for now I'd like to use RMS peak detection but I'm not sure how, once the signal has crossed the threshold, you ramp up the compression over the attack time.. Do you have to keep some sort of counter that knows how long the signal has been over the threshold, and ramps up the attenuation accordingly? I'm also not 100% on using buffers for realtime implementations. For the RMS detection should I work with the previous N samples to get my RMS value, or use some of the future samples from the buffer? As you can probably tell, I'm not the most experienced! So any advice you can offer would be very much appreciated! Thanks very much.
Help with envelope detector for compressor
Started by ●March 15, 2009
Reply by ●March 16, 20092009-03-16
On Mar 16, 6:18�am, "halfnormalled" <henrybou...@mac.com> wrote:> Hi guys, > > I'm pretty new to DSP. I've been implementing various effects in Matlab, > mostly using code from the DAFX book. I'm working on compressors at the > moment, actually trying to get one working in realtime in an Audio Unit.Is your pump working properly? a good air line is the best start for a compressor.
Reply by ●March 16, 20092009-03-16
halfnormalled wrote:> I'm working on compressors at the moment, actually trying to get > one working in realtime in an Audio Unit. I'm just having some > trouble visualising how the attack and release envelopes work.Try reading around the music-dsp archive. You can also look at and listen to what various open-source dynamics processors do. Here are some leads. http://www.google.com/search?q=compressor+attack+site:music.columbia.edu http://tap-plugins.sourceforge.net/ladspa/doubler.html http://quitte.de/dsp/caps.html http://plugin.org.uk/ Martin -- Quidquid latine scriptum est, altum videtur.
Reply by ●March 16, 20092009-03-16
On Mar 15, 1:18�pm, "halfnormalled" <henrybou...@mac.com> wrote:> Hi guys, > > I'm pretty new to DSP. I've been implementing various effects in Matlab, > mostly using code from the DAFX book. I'm working on compressors at the > moment, actually trying to get one working in realtime in an Audio Unit. > I'm just having some trouble visualising how the attack and release > envelopes work. > > To keep things simple for now I'd like to use RMS peak detection but I'm > not sure how, once the signal has crossed the threshold, you ramp up the > compression over the attack time.. Do you have to keep some sort of counter > that knows how long the signal has been over the threshold, and ramps up > the attenuation accordingly? > > I'm also not 100% on using buffers for realtime implementations. For the > RMS detection should I work with the previous N samples to get my RMS > value, or use some of the future samples from the buffer? > > As you can probably tell, I'm not the most experienced! So any advice you > can offer would be very much appreciated! > > Thanks very much.You could consider a dual time constant IIR lowpass filter operating on the envelope. Fast attack, slow decay or vice-versa. John
Reply by ●March 17, 20092009-03-17
>http://www.google.com/search?q=compressor+attack+site:music.columbia.edu >http://tap-plugins.sourceforge.net/ladspa/doubler.html >http://quitte.de/dsp/caps.html >http://plugin.org.uk/ >Those links are a big help thankyou! I managed to get a one pole lowpass working but I'm having some troubles getting the basic compressor functionality working. I've tried a few approaches, I'm wondering if anyone can suggest what I'm doing wrong, or if I'm otally going about this the wrong way. 1) Something simple that doesn't seem to work is going from linear to log. From what I understand this should yield an output exactly the same as the input. Yet I get horrible distortion when I run audio through this. Float32 log = log10(inputSample) * 20; Float32 linear = pow(10.0, log/20); outputSample = linear; 2) From the DAFX book it gives the control parameter of a compressor in the logarithic domain as: -CS(X-CT) CS being compressor slope which it gives the formula as 1-1/ratio X is input signal CT is threshold MY code is as follows if (inputSample > threshold) { // Compressor slope = 1-1/R slope = 1-(1/ratio); gainFunction = pow(10, -slope*(log10(abs(inputSample))-log10(threshold)) ); } else { gainFunction = 1; } Again I get distortion when the input exceeds the threshold. I've been using a maximum threshold value of 1. Is this wrong? I'm not sure how you find out what the values of the audio signal are (ie how to print them to an output console or something...) Does anyone have any suggestions? I know it's probably very basic stuff and I'm fully prepared for someone to tell me I'm stupid! :) Thanks
Reply by ●March 18, 20092009-03-18
halfnormalled wrote:> 1) Something simple that doesn't seem to work is going from > linear to log. From what I understand this should yield an > output exactly the same as the input. Yet I get horrible > distortion when I run audio through this. > > Float32 log = log10(inputSample) * 20;Stop and think about it. What's the logarithm's domain of definition? Can that command possibly be right?> 2) From the DAFX book it gives the control parameter of a > compressor in the logarithic domain as: > > -CS(X-CT) > > CS being compressor slope which it gives the formula as > 1-1/ratio > X is input signal > CT is thresholdI don't have that book handy, but I'm quite sure that X is *not* the input signal but the envelope signal, however detected. The same is definitely true in your first problem case. That is the fundamental difference between a dynamics processor and a waveshaper.> gainFunction = pow(10, > -slope*(log10(abs(inputSample))-log10(threshold))That's a wasteful formulation since pow() is just a combination of log() and exp(). When the threshold is given in linear units, as your code assumes, the nicest reduced expression is gain = pow(envelope*invThreshold, -slope) with invThreshold = 1/threshold precomputed. When the threshold is already in dB, write it in terms of exp() instead of pow() with the constant ln(10) precomputed.> I've been using a maximum threshold value of 1. Is this wrong?Depends. How is your audio stream scaled? The stream format docs should tell without you having to peek in and measure the numbers.> I'm not sure how you find out what the values of the audio > signal are (ie how to print them to an output console or > something...)Again, it depends on the way you're running the compressor. You can always allocate a console with OS-specific calls but I don't know the details involved. If you use Visual C++, take a look at http://arraydebugview.sourceforge.net/ . Also on Windows, you might use the OutputDebugString() API call and the DebugView app -- but don't try to log every sample; rather, accumulate statistics like min, max, or RMS values over one-second intervals or thereabouts. Martin -- Never make a shoddy design -- it could sell. --Karl Lagerfeld
Reply by ●March 18, 20092009-03-18
halfnormalled wrote:> 1) Something simple that doesn't seem to work is going from > linear to log. From what I understand this should yield an > output exactly the same as the input. Yet I get horrible > distortion when I run audio through this. > > Float32 log = log10(inputSample) * 20;Stop and think about it. What's the logarithm's domain of definition? Can that command possibly be right?> 2) From the DAFX book it gives the control parameter of a > compressor in the logarithic domain as: > > -CS(X-CT) > > CS being compressor slope which it gives the formula as > 1-1/ratio > X is input signal > CT is thresholdI don't have that book handy, but I'm quite sure that X is *not* the input signal but the envelope signal, however detected. The same is definitely true in your first problem case. That is the fundamental difference between a dynamics processor and a waveshaper.> gainFunction = pow(10, > -slope*(log10(abs(inputSample))-log10(threshold))That's a wasteful formulation since pow() is just a combination of log() and exp(). When the threshold is given in linear units, as your code assumes, the nicest reduced expression is gain = pow(envelope*invThreshold, -slope) with invThreshold = 1/threshold precomputed. When the threshold is already in dB, write it in terms of exp() instead of pow() with the constant ln(10) precomputed.> I've been using a maximum threshold value of 1. Is this wrong?Depends. How is your audio stream scaled? The stream format docs should tell without you having to peek in and measure the numbers.> I'm not sure how you find out what the values of the audio > signal are (ie how to print them to an output console or > something...)Again, it depends on the way you're running the compressor. You can always allocate a console with OS-specific calls but I don't know the details involved. If you use Visual C++, take a look at http://arraydebugview.sourceforge.net/ . Also on Windows, you might use the OutputDebugString() API call and the DebugView app -- but don't try to log every sample; rather, accumulate statistics like min, max, or RMS values over one-second intervals or thereabouts. Martin -- Never make a shoddy design -- it could sell. --Karl Lagerfeld
Reply by ●March 18, 20092009-03-18
Thanks Martin, some very useful info in there. Sorry if my questions seem a bit basic I'm trying my best to understand it all, I just need to get an example working and things normally start to click into place once that happens!
Reply by ●March 18, 20092009-03-18
>> Float32 log = log10(inputSample) * 20; > >Stop and think about it. What's the logarithm's domain of definition? >Can that command possibly be right?Excuse my ignorance. Why is this wrong? Does this not work mathematically? y = log10(x) x = 10^y So surely: log10(x) * 20 = y 10^(y/20) = x No? (I'm very prepared to be proved wrong :) ) I'm thinking in decibels possibly I need inputSample over some reference value? Would this be right? If so what would you use for the reference value? the highest value for the input stream (whatever that may be.....)
Reply by ●March 18, 20092009-03-18
Martin Eisenberg <martin.eisenberg@udo.edu> wrote:> halfnormalled wrote:>> 1) Something simple that doesn't seem to work is going from >> linear to log. From what I understand this should yield an >> output exactly the same as the input. Yet I get horrible >> distortion when I run audio through this.>> Float32 log = log10(inputSample) * 20;> Stop and think about it. What's the logarithm's domain of definition? > Can that command possibly be right?Why is it that in languages like Fortran log() is defined for complex numbers, but log10() only for real numbers? The only difference is a scale factor, which should be just as valid for complex numbers. I wrote a program not so long ago that computes some statistics on WAV files. Some are the peak and RMS amplitude. When I first started with 16 bit WAV I could sum the square in a 64 bit integer. With 24 bits, though, it would overflow and gave the wrong results. Anyway, I compute the RMS and then take the log, not the other way around. -- glen






