Csound Csound-dev Csound-tekno Search About

Re: Compressor/Limiter

Date1999-10-29 18:47
FromPaul Winkler
SubjectRe: Compressor/Limiter
"Michael A. Thompson" wrote:
> 
> Looking for a good compressor/limiter csound .orc. Anybody messed around
> with doing one?

Funny you should ask, I've been working on this lately.
csound has a "dam" opcode that's supposed to be a general-purpose
dynamics processor, but I can't get it to sound good.

Here's where I left off on my compressor instr. THe big difficulty
seems to be implementing "attack" and "decay" in ways that work like
an analog compressor, since it's rarely desirable to have a
compressor that works instantaneously all the time. This version
sort-of does the trick.

Next step is to add a threshold level and different ratios above/
below that level. Not sure how to do that yet. I had some good
exchanges with Paul Barton-Davis where we tried to figure out how
that worked; I think his idea of using an ftable to plot input level
vs. output gain might be the best approach, since it allows multiple
threshold levels and arbitrary dynamics curves.


instr 14    ; do everything in dB. 
            ; Attack/release added using my by-hand linear slope
method.
        ; Let's see if I can make this work right with ratio (that
is,
        ; ratio of 1 "turns off" attack/release controls...)
        ; OK, this is getting there....

        ; EXTRACT & COMPRESS ENVELOPE
iratio = 1 / p4   ; p4 is "compression ratio" -- 4 means 4:1 
ihp = 10          ; lopass filter freq for rms and gain

kenv expseg 1, p3 - .1, 32767, .1, 32767
kdclick linseg 0, .1, 1, p3 -.1, 1
asig, asig2 diskin "arms/salt_notice/nines.wav", 1 ; ,  217
avg = (asig + asig2) * .5
krms_raw rms avg, ihp, 0
kdb_raw = 20 * log10(krms_raw + 1)  ; + 1 to avoid divide by 0
kdb_comp = kdb_raw * iratio

ioffset =  72 - (72 * iratio) ; I thought it should be 90 d
                              ; but that doesn't work right at high
                              ; ratios. 
                              ;  70 catches peaks pretty well.

kdb_comp = kdb_comp + ioffset ; make-up gain.
kdiff = kdb_comp - kdb_raw                      ; difference


            ; SLOPE CONTROL (attack & release)
iattack = p6       ; MAX time for level to RISE 60 dB
irelease = p7      ; MIN time for level to DROP 60 dB
            ; Now we translate that into maximum diff. between
successive
            ; values of k-rate DIFFERENCE
imaxattd = (90 * iratio) / (kr * iattack ); "max. attack difference"
imaxreld = (90 * iratio) / (kr * irelease)
print iattack, imaxattd
print irelease, imaxreld
kdiff_old init 88

if (kdiff > kdiff_old) goto RELEASE
ATTACK:
;  khalftime = iattack  ; fast attack
;  ;                ; this works???
goto OUTPUT

RELEASE:
        ; This sort-of works...
if (kdiff_old + imaxreld) > kdiff goto OUTPUT
kdiff = kdiff_old + imaxreld

OUTPUT:

kdiff_old = kdiff            ; store for next cycle

            ; FINAL OUTPUT GAIN CONTROL ...
kdb_comp = kdb_raw + kdiff      ; construct final target gain
krms_comp = 10 ^ (kdb_comp / 20) ; convert back to rms.
aout1 gain asig, krms_comp, ihp, 1    ; set gain to match RMS
aout2 gain asig2, krms_comp, ihp, 1
; asig, rms,  filter hz, initial (0=clear, 1 prevents clicks)

imakeup = p5                                    ; NOT USED

  outs aout1, aout2
endin


;;;;;;;;;; here's a test sco.

; First uncompressed, then compressed with fast attack & release,
; then fast attack / slow release.

f1 0 1024 10 1                          ; sine

;14     at      dur     ratio   gain    attack  release
i14     1       6       1       1       .000001      .0001
i14     7.5       .      8       1       .000001      .00000001
i14     14       .       8       2       .000001      .5




----------------    paul winkler    ------------------
slinkP arts:  music, sound, illustration, design, etc.
email=========================slinkp AT ulster DOT net
ARMS online=======================http://reacharms.com    
personal page===========http://www.ulster.net/~abigoo/