compressors.lib
Compressors library. Its official prefix is co.
This library provides building blocks and complete dynamic processors including compressors, limiters, expanders, and gates.
The Compressors library is organized into 7 sections:
- Conversion Tools
- Functions Reference
- Linear gain computer section
- Original versions section
- Expanders
- Lookahead Limiters
- Multiband Compressors
References
Conversion Tools
Most compressors have a ratio parameter to define the amount of compression. A ratio of 1 means no compression, a ratio of 2 means that for every dB the input goes above the threshold, the output gets turned down half a dB. To use a compressor as a brick wall limiter, the ratio needs to be infinity. This is hard to express in a Faust UI element, and overcompression can not be expressed at all, therefore most compressors in this library use a strength parameter instead, where 0 means no compression, 1 means hard limiting and bigger than 1 means over-compression.
(co.)ratio2strength
This utility converts a ratio to a strength.
Usage
ratio2strength(ratio) : _
Where:
ratio: compression ratio, between 1 and infinity (1=no compression, infinity means hard limiting)
Test
co = library("compressors.lib");
ratio2strength_test = co.ratio2strength(4);
(co.)strength2ratio
This utility converts a strength to a ratio.
Usage
strength2ratio(strength) : _
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)
Test
co = library("compressors.lib");
strength2ratio_test = co.strength2ratio(0.75);
Functions Reference
(co.)peak_compression_gain_mono_db
Mono dynamic range compressor gain computer with dB output.
peak_compression_gain_mono_db is a standard Faust function.
Usage
_ : peak_compression_gain_mono_db(strength,thresh,att,rel,knee,prePost) : _
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detector
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
no = library("noises.lib");
peak_compression_gain_mono_db_test = os.tosc(440) : co.peak_compression_gain_mono_db(0.5, -12, 0.01, 0.1, 6, 0);
peak_compression_gain_mono_db_slider_test = os.tosc(440) : co.peak_compression_gain_mono_db(hslider("peak_compression_gain_mono_db:strength", 0.5, 0, 1, 0.01), hslider("peak_compression_gain_mono_db:thresh", -12, -60, 0, 0.1), hslider("peak_compression_gain_mono_db:att", 0.01, 0, 1, 0.001), hslider("peak_compression_gain_mono_db:rel", 0.1, 0, 1, 0.001), hslider("peak_compression_gain_mono_db:knee", 6, 0, 30, 0.1), hslider("peak_compression_gain_mono_db:prePost", 0, 0, 1, 1));
peak_compression_gain_mono_db_post_test = no.noise*e : co.peak_compression_gain_mono_db(0.5, -24, 0.01, 0.1, 6, 1) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); };
peak_compression_gain_mono_db_modulated_test = no.noise*e : co.peak_compression_gain_mono_db(0.5, -24, 0.001, 0.001*pow(1000, tri), 6, 0) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
peak_compression_gain_mono_db_jump_test = no.noise*e : co.peak_compression_gain_mono_db(0.5, -24, 0.001, 0.001*pow(1000, sq), 6, 0) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); sq = ba.period(2*P) < P; };
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)peak_compression_gain_N_chan_db
N channels dynamic range compressor gain computer with dB output.
peak_compression_gain_N_chan_db is a standard Faust function.
Usage
si.bus(N) : peak_compression_gain_N_chan_db(strength,thresh,att,rel,knee,prePost,link,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionN: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
peak_compression_gain_N_chan_db_test = (os.tosc(440), os.tosc(660)) : co.peak_compression_gain_N_chan_db(0.5, -12, 0.01, 0.1, 6, 0, 0.5, 2);
peak_compression_gain_N_chan_db_slider_test = (os.tosc(440), os.tosc(660)) : co.peak_compression_gain_N_chan_db(hslider("peak_compression_gain_N_chan_db:strength", 0.5, 0, 1, 0.01), hslider("peak_compression_gain_N_chan_db:thresh", -12, -60, 0, 0.1), hslider("peak_compression_gain_N_chan_db:att", 0.01, 0, 1, 0.001), hslider("peak_compression_gain_N_chan_db:rel", 0.1, 0, 1, 0.001), hslider("peak_compression_gain_N_chan_db:knee", 6, 0, 30, 0.1), hslider("peak_compression_gain_N_chan_db:prePost", 0, 0, 1, 1), hslider("peak_compression_gain_N_chan_db:link", 0.5, 0, 1, 0.01), 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)FFcompressor_N_chan
Feed forward N channels dynamic range compressor.
FFcompressor_N_chan is a standard Faust function.
Usage
si.bus(N) : FFcompressor_N_chan(strength,thresh,att,rel,knee,prePost,link,meter,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionmeter: a gain reduction meter. It can be implemented like so:meter = _<:(_, (ba.linear2db:max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;N: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
meter(x) = x;
FFcompressor_N_chan_test = (os.tosc(440), os.tosc(660)) : co.FFcompressor_N_chan(0.5, -12, 0.01, 0.1, 6, 0, 0.5, meter, 2);
FFcompressor_N_chan_slider_test = (os.tosc(440), os.tosc(660)) : co.FFcompressor_N_chan(hslider("FFcompressor_N_chan:strength", 0.5, 0, 1, 0.01), hslider("FFcompressor_N_chan:thresh", -12, -60, 0, 0.1), hslider("FFcompressor_N_chan:att", 0.01, 0, 1, 0.001), hslider("FFcompressor_N_chan:rel", 0.1, 0, 1, 0.001), hslider("FFcompressor_N_chan:knee", 6, 0, 30, 0.1), hslider("FFcompressor_N_chan:prePost", 0, 0, 1, 1), hslider("FFcompressor_N_chan:link", 0.5, 0, 1, 0.01), meter, 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)FBcompressor_N_chan
Feed back N channels dynamic range compressor.
FBcompressor_N_chan is a standard Faust function.
Usage
si.bus(N) : FBcompressor_N_chan(strength,thresh,att,rel,knee,prePost,link,meter,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels. 0 = each channel is independent, 1 = all channels have the same amount of gain reductionmeter: a gain reduction meter. It can be implemented with:meter = _ <: (_,(ba.linear2db:max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;or it can be omitted by definingmeter = _;.N: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
no = library("noises.lib");
meter(x) = x;
FBcompressor_N_chan_test = (os.tosc(440), os.tosc(660)) : co.FBcompressor_N_chan(0.5, -12, 0.01, 0.1, 6, 0, 0.5, meter, 2);
FBcompressor_N_chan_slider_test = (os.tosc(440), os.tosc(660)) : co.FBcompressor_N_chan(hslider("FBcompressor_N_chan:strength", 0.5, 0, 1, 0.01), hslider("FBcompressor_N_chan:thresh", -12, -60, 0, 0.1), hslider("FBcompressor_N_chan:att", 0.01, 0, 1, 0.001), hslider("FBcompressor_N_chan:rel", 0.1, 0, 1, 0.001), hslider("FBcompressor_N_chan:knee", 6, 0, 30, 0.1), hslider("FBcompressor_N_chan:prePost", 0, 0, 1, 1), hslider("FBcompressor_N_chan:link", 0.5, 0, 1, 0.01), meter, 2);
FBcompressor_N_chan_modulated_test = par(i, 2, no.noises(2, i)*e) : co.FBcompressor_N_chan(0.5, -24, 0.001*pow(100, tri), 0.001*pow(1000, 1 - tri), 6, 0, 0.5, meter, 2) with { meter(x) = x; e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
FBcompressor_N_chan_jump_test = par(i, 2, no.noises(2, i)*e) : co.FBcompressor_N_chan(0.5, -24, 0.001*pow(100, sq), 0.001*pow(1000, 1 - sq), 6, 0, 0.5, meter, 2) with { meter(x) = x; e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); sq = ba.period(2*P) < P; };
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)FBFFcompressor_N_chan
Feed forward / feed back N channels dynamic range compressor.
The feedback part has a much higher strength, so they end up sounding similar.
FBFFcompressor_N_chan is a standard Faust function.
Usage
si.bus(N) : FBFFcompressor_N_chan(strength,thresh,att,rel,knee,prePost,link,FBFF,meter,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionFBFF: fade between feed forward (0) and feed back (1) compressionmeter: a gain reduction meter. It can be implemented like so:meter = _<:(_,(max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;N: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
meter(x) = x;
FBFFcompressor_N_chan_test = (os.tosc(440), os.tosc(660)) : co.FBFFcompressor_N_chan(0.4, -12, 0.01, 0.1, 6, 0, 0.5, 0.3, meter, 2);
FBFFcompressor_N_chan_slider_test = (os.tosc(440), os.tosc(660)) : co.FBFFcompressor_N_chan(hslider("FBFFcompressor_N_chan:strength", 0.4, 0, 1, 0.01), hslider("FBFFcompressor_N_chan:thresh", -12, -60, 0, 0.1), hslider("FBFFcompressor_N_chan:att", 0.01, 0, 1, 0.001), hslider("FBFFcompressor_N_chan:rel", 0.1, 0, 1, 0.001), hslider("FBFFcompressor_N_chan:knee", 6, 0, 30, 0.1), hslider("FBFFcompressor_N_chan:prePost", 0, 0, 1, 1), hslider("FBFFcompressor_N_chan:link", 0.5, 0, 1, 0.01), hslider("FBFFcompressor_N_chan:FBFF", 0.3, 0, 1, 0.01), meter, 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)RMS_compression_gain_mono_db
Mono RMS dynamic range compressor gain computer with dB output.
RMS_compression_gain_mono_db is a standard Faust function.
Usage
_ : RMS_compression_gain_mono_db(strength,thresh,att,rel,knee,prePost) : _
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detector
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
no = library("noises.lib");
RMS_compression_gain_mono_db_test = os.tosc(330) : co.RMS_compression_gain_mono_db(0.5, -18, 0.02, 0.12, 6, 0);
RMS_compression_gain_mono_db_slider_test = os.tosc(330) : co.RMS_compression_gain_mono_db(hslider("RMS_compression_gain_mono_db:strength", 0.5, 0, 1, 0.01), hslider("RMS_compression_gain_mono_db:thresh", -18, -60, 0, 0.1), hslider("RMS_compression_gain_mono_db:att", 0.02, 0, 1, 0.001), hslider("RMS_compression_gain_mono_db:rel", 0.12, 0, 1, 0.001), hslider("RMS_compression_gain_mono_db:knee", 6, 0, 30, 0.1), hslider("RMS_compression_gain_mono_db:prePost", 0, 0, 1, 1));
RMS_compression_gain_mono_db_modulated_test = no.noise*e : co.RMS_compression_gain_mono_db(0.5, -24, 0.001*pow(1000, tri), 0.12, 6, 0) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
RMS_compression_gain_mono_db_jump_test = no.noise*e : co.RMS_compression_gain_mono_db(0.5, -24, 0.001*pow(1000, sq), 0.12, 6, 0) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); sq = ba.period(2*P) < P; };
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)RMS_compression_gain_N_chan_db
RMS N channels dynamic range compressor gain computer with dB output.
RMS_compression_gain_N_chan_db is a standard Faust function.
Usage
si.bus(N) : RMS_compression_gain_N_chan_db(strength,thresh,att,rel,knee,prePost,link,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionN: the number of channels of the compressor
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
RMS_compression_gain_N_chan_db_test = (os.tosc(330), os.tosc(550)) : co.RMS_compression_gain_N_chan_db(0.5, -18, 0.02, 0.12, 6, 0, 0.5, 2);
RMS_compression_gain_N_chan_db_slider_test = (os.tosc(330), os.tosc(550)) : co.RMS_compression_gain_N_chan_db(hslider("RMS_compression_gain_N_chan_db:strength", 0.5, 0, 1, 0.01), hslider("RMS_compression_gain_N_chan_db:thresh", -18, -60, 0, 0.1), hslider("RMS_compression_gain_N_chan_db:att", 0.02, 0, 1, 0.001), hslider("RMS_compression_gain_N_chan_db:rel", 0.12, 0, 1, 0.001), hslider("RMS_compression_gain_N_chan_db:knee", 6, 0, 30, 0.1), hslider("RMS_compression_gain_N_chan_db:prePost", 0, 0, 1, 1), hslider("RMS_compression_gain_N_chan_db:link", 0.5, 0, 1, 0.01), 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)RMS_FBFFcompressor_N_chan
RMS feed forward / feed back N channels dynamic range compressor.
The feedback part has a much higher strength, so they end up sounding similar.
RMS_FBFFcompressor_N_chan is a standard Faust function.
Usage
si.bus(N) : RMS_FBFFcompressor_N_chan(strength,thresh,att,rel,knee,prePost,link,FBFF,meter,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionFBFF: fade between feed forward (0) and feed back (1) compression.meter: a gain reduction meter. It can be implemented with:meter = _<:(_,(max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;N: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
To save CPU we cheat a bit, in a similar way as in the original libs:
instead of crosfading between two sets of gain calculators as above,
we take the abs of the audio from both the FF and FB, and crossfade between those,
and feed that into one set of gain calculators
again the strength is much higher when in FB mode, but implemented differently.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
meter(x) = x;
RMS_FBFFcompressor_N_chan_test = (os.tosc(330), os.tosc(550)) : co.RMS_FBFFcompressor_N_chan(0.4, -18, 0.02, 0.12, 6, 0, 0.5, 0.3, meter, 2);
RMS_FBFFcompressor_N_chan_slider_test = (os.tosc(330), os.tosc(550)) : co.RMS_FBFFcompressor_N_chan(hslider("RMS_FBFFcompressor_N_chan:strength", 0.4, 0, 1, 0.01), hslider("RMS_FBFFcompressor_N_chan:thresh", -18, -60, 0, 0.1), hslider("RMS_FBFFcompressor_N_chan:att", 0.02, 0, 1, 0.001), hslider("RMS_FBFFcompressor_N_chan:rel", 0.12, 0, 1, 0.001), hslider("RMS_FBFFcompressor_N_chan:knee", 6, 0, 30, 0.1), hslider("RMS_FBFFcompressor_N_chan:prePost", 0, 0, 1, 1), hslider("RMS_FBFFcompressor_N_chan:link", 0.5, 0, 1, 0.01), hslider("RMS_FBFFcompressor_N_chan:FBFF", 0.3, 0, 1, 0.01), meter, 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)RMS_FBcompressor_peak_limiter_N_chan
N channel RMS feed back compressor into peak limiter feeding back into the FB compressor.
By combining them this way, they complement each other optimally:
the RMS compressor doesn't have to deal with the peaks,
and the peak limiter get's spared from the steady state signal.
The feedback part has a much higher strength, so they end up sounding similar.
RMS_FBcompressor_peak_limiter_N_chan is a standard Faust function.
Usage
si.bus(N) : RMS_FBcompressor_peak_limiter_N_chan(strength,thresh,threshLim,att,rel,knee,link,meter,meterLim,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inthreshLim: dB level threshold above which the brickwall limiter kicks inatt: attack time = time constant (sec) when level & compression going up this is also used as the release time of the limiterrel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reduction the limiter uses a knee half this sizelink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionmeter: compressor gain reduction meter. It can be implemented with:meter = _<:(_,(max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;meterLim: brickwall limiter gain reduction meter. It can be implemented with:meterLim = _<:(_,(max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;N: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
meter(x) = x;
meterLim(x) = x;
RMS_FBcompressor_peak_limiter_N_chan_test = (os.tosc(330), os.tosc(550)) : co.RMS_FBcompressor_peak_limiter_N_chan(0.4, -18, -2, 0.02, 0.12, 6, 0.5, meter, meterLim, 2);
RMS_FBcompressor_peak_limiter_N_chan_slider_test = (os.tosc(330), os.tosc(550)) : co.RMS_FBcompressor_peak_limiter_N_chan(hslider("RMS_FBcompressor_peak_limiter_N_chan:strength", 0.4, 0, 1, 0.01), hslider("RMS_FBcompressor_peak_limiter_N_chan:thresh", -18, -60, 0, 0.1), hslider("RMS_FBcompressor_peak_limiter_N_chan:threshLim", -2, -60, 0, 0.1), hslider("RMS_FBcompressor_peak_limiter_N_chan:att", 0.02, 0, 1, 0.001), hslider("RMS_FBcompressor_peak_limiter_N_chan:rel", 0.12, 0, 1, 0.001), hslider("RMS_FBcompressor_peak_limiter_N_chan:knee", 6, 0, 30, 0.1), hslider("RMS_FBcompressor_peak_limiter_N_chan:link", 0.5, 0, 1, 0.01), meter, meterLim, 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
Linear gain computer section
The gain computer functions in this section have been replaced by a version that outputs dBs, but we retain the linear output version for backward compatibility.
(co.)peak_compression_gain_mono
Mono dynamic range compressor gain computer with linear output.
peak_compression_gain_mono is a standard Faust function.
Usage
_ : peak_compression_gain_mono(strength,thresh,att,rel,knee,prePost) : _
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detector
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
peak_compression_gain_mono_test = os.tosc(440) : co.peak_compression_gain_mono(0.5, -12, 0.01, 0.1, 6, 0);
peak_compression_gain_mono_slider_test = os.tosc(440) : co.peak_compression_gain_mono(hslider("peak_compression_gain_mono:strength", 0.5, 0, 1, 0.01), hslider("peak_compression_gain_mono:thresh", -12, -60, 0, 0.1), hslider("peak_compression_gain_mono:att", 0.01, 0, 1, 0.001), hslider("peak_compression_gain_mono:rel", 0.1, 0, 1, 0.001), hslider("peak_compression_gain_mono:knee", 6, 0, 30, 0.1), hslider("peak_compression_gain_mono:prePost", 0, 0, 1, 1));
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)peak_compression_gain_N_chan
N channels dynamic range compressor gain computer with linear output.
peak_compression_gain_N_chan is a standard Faust function.
Usage
si.bus(N) : peak_compression_gain_N_chan(strength,thresh,att,rel,knee,prePost,link,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionN: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
peak_compression_gain_N_chan_test = (os.tosc(440), os.tosc(660)) : co.peak_compression_gain_N_chan(0.5, -12, 0.01, 0.1, 6, 0, 0.5, 2);
peak_compression_gain_N_chan_slider_test = (os.tosc(440), os.tosc(660)) : co.peak_compression_gain_N_chan(hslider("peak_compression_gain_N_chan:strength", 0.5, 0, 1, 0.01), hslider("peak_compression_gain_N_chan:thresh", -12, -60, 0, 0.1), hslider("peak_compression_gain_N_chan:att", 0.01, 0, 1, 0.001), hslider("peak_compression_gain_N_chan:rel", 0.1, 0, 1, 0.001), hslider("peak_compression_gain_N_chan:knee", 6, 0, 30, 0.1), hslider("peak_compression_gain_N_chan:prePost", 0, 0, 1, 1), hslider("peak_compression_gain_N_chan:link", 0.5, 0, 1, 0.01), 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)RMS_compression_gain_mono
Mono RMS dynamic range compressor gain computer with linear output.
RMS_compression_gain_mono is a standard Faust function.
Usage
_ : RMS_compression_gain_mono(strength,thresh,att,rel,knee,prePost) : _
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detector
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
RMS_compression_gain_mono_test = os.tosc(330) : co.RMS_compression_gain_mono(0.5, -18, 0.02, 0.12, 6, 0);
RMS_compression_gain_mono_slider_test = os.tosc(330) : co.RMS_compression_gain_mono(hslider("RMS_compression_gain_mono:strength", 0.5, 0, 1, 0.01), hslider("RMS_compression_gain_mono:thresh", -18, -60, 0, 0.1), hslider("RMS_compression_gain_mono:att", 0.02, 0, 1, 0.001), hslider("RMS_compression_gain_mono:rel", 0.12, 0, 1, 0.001), hslider("RMS_compression_gain_mono:knee", 6, 0, 30, 0.1), hslider("RMS_compression_gain_mono:prePost", 0, 0, 1, 1));
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
(co.)RMS_compression_gain_N_chan
RMS N channels dynamic range compressor gain computer with linear output.
RMS_compression_gain_N_chan is a standard Faust function.
Usage
si.bus(N) : RMS_compression_gain_N_chan(strength,thresh,att,rel,knee,prePost,link,N) : si.bus(N)
Where:
strength: strength of the compression (0 = no compression, 1 means hard limiting, >1 means over-compression)thresh: dB level threshold above which compression kicks inatt: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compressionknee: a gradual increase in gain reduction around the threshold: below thresh-(knee/2) there is no gain reduction, above thresh+(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-threshold detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionN: the number of channels of the compressor, known at compile time
It uses a strength parameter instead of the traditional ratio, in order to be able to function as a hard limiter. For that you'd need a ratio of infinity:1, and you cannot express that in Faust.
Sometimes even bigger ratios are useful: for example a group recording where one instrument is recorded with both a close microphone and a room microphone, and the instrument is loud enough in the room mic when playing loud, but you want to boost it when it is playing soft.
Test
co = library("compressors.lib");
os = library("oscillators.lib");
RMS_compression_gain_N_chan_test = (os.tosc(330), os.tosc(550)) : co.RMS_compression_gain_N_chan(0.5, -18, 0.02, 0.12, 6, 0, 0.5, 2);
RMS_compression_gain_N_chan_slider_test = (os.tosc(330), os.tosc(550)) : co.RMS_compression_gain_N_chan(hslider("RMS_compression_gain_N_chan:strength", 0.5, 0, 1, 0.01), hslider("RMS_compression_gain_N_chan:thresh", -18, -60, 0, 0.1), hslider("RMS_compression_gain_N_chan:att", 0.02, 0, 1, 0.001), hslider("RMS_compression_gain_N_chan:rel", 0.12, 0, 1, 0.001), hslider("RMS_compression_gain_N_chan:knee", 6, 0, 30, 0.1), hslider("RMS_compression_gain_N_chan:prePost", 0, 0, 1, 1), hslider("RMS_compression_gain_N_chan:link", 0.5, 0, 1, 0.01), 2);
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- Digital Dynamic Range Compressor Design: A Tutorial and Analysis, Dimitrios GIANNOULIS (Dimitrios.Giannoulis@eecs.qmul.ac.uk), Michael MASSBERG (michael@massberg.org), and Josuah D.REISS (josh.reiss@eecs.qmul.ac.uk)
Original versions section
The functions in this section are largely superseded by the limiters above, but we retain them for backward compatibility and for situations in which a more permissive, MIT-style license is required.
(co.)compressor_lad_mono
Mono dynamic range compressor with lookahead delay.
compressor_lad_mono is a standard Faust function.
Usage
_ : compressor_lad_mono(lad,ratio,thresh,att,rel) : _
Where:
lad: lookahead delay in seconds (nonnegative) - gets rounded to nearest sample. The effective attack time is a good settingratio: compression ratio (1 = no compression, >1 means compression) Ratios: 4 is moderate compression, 8 is strong compression, 12 is mild limiting, and 20 is pretty hard limiting at the thresholdthresh: dB level threshold above which compression kicks in (0 dB = max level)att: attack time = time constant (sec) when level & compression are going uprel: release time = time constant (sec) coming out of compression
Test
co = library("compressors.lib");
os = library("oscillators.lib");
compressor_lad_mono_test = os.tosc(440) : co.compressor_lad_mono(0.005, 4, -9, 0.01, 0.1);
compressor_lad_mono_slider_test = os.tosc(440) : co.compressor_lad_mono(hslider("compressor_lad_mono:lad", 0.005, 0, 0.1, 0.001), hslider("compressor_lad_mono:ratio", 4, 1, 20, 0.1), hslider("compressor_lad_mono:thresh", -9, -60, 0, 0.1), hslider("compressor_lad_mono:att", 0.01, 0, 1, 0.001), hslider("compressor_lad_mono:rel", 0.1, 0, 1, 0.001));
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- https://ccrma.stanford.edu/~jos/filters/Nonlinear_Filter_Example_Dynamic.html
- Albert Graef's "faust2pd"/examples/synth/compressor_.dsp
- More features: https://github.com/magnetophon/faustCompressors
(co.)compressor_mono
Mono dynamic range compressors.
compressor_mono is a standard Faust function.
Usage
_ : compressor_mono(ratio,thresh,att,rel) : _
Where:
ratio: compression ratio (1 = no compression, >1 means compression) Ratios: 4 is moderate compression, 8 is strong compression, 12 is mild limiting, and 20 is pretty hard limiting at the thresholdthresh: dB level threshold above which compression kicks in (0 dB = max level)att: attack time = time constant (sec) when level & compression are going uprel: release time = time constant (sec) coming out of compression
Test
co = library("compressors.lib");
os = library("oscillators.lib");
compressor_mono_test = os.tosc(440) : co.compressor_mono(4, -9, 0.01, 0.2);
compressor_mono_slider_test = os.tosc(440) : co.compressor_mono(hslider("compressor_mono:ratio", 4, 1, 20, 0.1), hslider("compressor_mono:thresh", -9, -60, 0, 0.1), hslider("compressor_mono:att", 0.01, 0, 1, 0.001), hslider("compressor_mono:rel", 0.2, 0, 1, 0.001));
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- https://ccrma.stanford.edu/~jos/filters/Nonlinear_Filter_Example_Dynamic.html
- Albert Graef's "faust2pd"/examples/synth/compressor_.dsp
- More features: https://github.com/magnetophon/faustCompressors
(co.)compressor_stereo
Stereo dynamic range compressors.
Usage
_,_ : compressor_stereo(ratio,thresh,att,rel) : _,_
Where:
ratio: compression ratio (1 = no compression, >1 means compression)thresh: dB level threshold above which compression kicks in (0 dB = max level)att: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compression
Test
co = library("compressors.lib");
os = library("oscillators.lib");
compressor_stereo_test = (os.tosc(440), os.tosc(660)) : co.compressor_stereo(4, -9, 0.01, 0.2);
compressor_stereo_slider_test = (os.tosc(440), os.tosc(660)) : co.compressor_stereo(hslider("compressor_stereo:ratio", 4, 1, 20, 0.1), hslider("compressor_stereo:thresh", -9, -60, 0, 0.1), hslider("compressor_stereo:att", 0.01, 0, 1, 0.001), hslider("compressor_stereo:rel", 0.2, 0, 1, 0.001));
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- https://ccrma.stanford.edu/~jos/filters/Nonlinear_Filter_Example_Dynamic.html
- Albert Graef's "faust2pd"/examples/synth/compressor_.dsp
- More features: https://github.com/magnetophon/faustCompressors
(co.)compression_gain_mono
Compression-gain calculation for dynamic range compressors.
Usage
_ : compression_gain_mono(ratio,thresh,att,rel) : _
Where:
ratio: compression ratio (1 = no compression, >1 means compression)thresh: dB level threshold above which compression kicks in (0 dB = max level)att: attack time = time constant (sec) when level & compression going uprel: release time = time constant (sec) coming out of compression
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
no = library("noises.lib");
compression_gain_mono_test = os.tosc(440) : co.compression_gain_mono(4, -9, 0.01, 0.2);
compression_gain_mono_slider_test = os.tosc(440) : co.compression_gain_mono(hslider("compression_gain_mono:ratio", 4, 1, 20, 0.1), hslider("compression_gain_mono:thresh", -9, -60, 0, 0.1), hslider("compression_gain_mono:att", 0.01, 0, 1, 0.001), hslider("compression_gain_mono:rel", 0.2, 0, 1, 0.001));
compression_gain_mono_modulated_test = no.noise*e : co.compression_gain_mono(4, -24, 0.001*pow(100, tri), 0.001*pow(1000, 1 - tri)) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
compression_gain_mono_jump_test = no.noise*e : co.compression_gain_mono(4, -24, 0.001*pow(100, sq), 0.001*pow(1000, 1 - sq)) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); sq = ba.period(2*P) < P; };
References
- http://en.wikipedia.org/wiki/Dynamic_range_compression
- https://ccrma.stanford.edu/~jos/filters/Nonlinear_Filter_Example_Dynamic.html
- Albert Graef's "faust2pd"/examples/synth/compressor_.dsp
- More features: https://github.com/magnetophon/faustCompressors
(co.)limiter_1176_R4_mono
A limiter guards against hard-clipping. It can be implemented as a compressor having a high threshold (near the clipping level), fast attack, and high ratio. Since the compression ratio is so high, some knee smoothing is desirable (for softer limiting). This example is intended to get you started using compressors as limiters, so all parameters are hardwired here to nominal values.
ratio: 4 (moderate compression).
See compressor_mono comments for a guide to other choices.
Mike Shipley likes this (lowest) setting on the 1176.
(Grammy award-winning mixer for Queen, Tom Petty, etc.).
thresh: -6 dB, meaning 4:1 compression begins at amplitude 1/2.
att: 800 MICROseconds (Note: scaled by ratio in the 1176)
The 1176 range is said to be 20-800 microseconds.
Faster attack gives "more bite" (e.g. on vocals),
and makes hard-clipping less likely on fast overloads.
rel: 0.5 s (Note: scaled by ratio in the 1176)
The 1176 range is said to be 50-1100 ms.
The 1176 also has a "bright, clear eq effect" (use filters.lib if desired).
limiter_1176_R4_mono is a standard Faust function.
Usage
_ : limiter_1176_R4_mono : _
Test
co = library("compressors.lib");
os = library("oscillators.lib");
limiter_1176_R4_mono_test = os.tosc(440) : co.limiter_1176_R4_mono;
References
(co.)limiter_1176_R4_stereo
A limiter guards against hard-clipping. It can be
implemented as a compressor having a high threshold (near the
clipping level), fast attack and release, and high ratio. Since
the ratio is so high, some knee smoothing is
desirable ("soft limiting"). This example is intended
to get you started using compressor_* as a limiter, so all
parameters are hardwired to nominal values here.
ratio: 4 (moderate compression), 8 (severe compression),
12 (mild limiting), or 20 to 1 (hard limiting).
att: 20-800 MICROseconds (Note: scaled by ratio in the 1176).
rel: 50-1100 ms (Note: scaled by ratio in the 1176).
Mike Shipley likes 4:1 (Grammy-winning mixer for Queen, Tom Petty, etc.) Faster attack gives "more bite" (e.g. on vocals). He hears a bright, clear eq effect as well (not implemented here).
Usage
_,_ : limiter_1176_R4_stereo : _,_
Test
co = library("compressors.lib");
os = library("oscillators.lib");
limiter_1176_R4_stereo_test = (os.tosc(440), os.tosc(660)) : co.limiter_1176_R4_stereo;
References
Expanders
(co.)peak_expansion_gain_N_chan_db
N channels dynamic range expander gain computer.
peak_expansion_gain_N_chan_db is a standard Faust function.
Usage
si.bus(N) : peak_expansion_gain_N_chan_db(strength,thresh,range,att,hold,rel,knee,prePost,link,maxHold,N) : si.bus(N)
Where:
strength: strength of the expansion (0 = no expansion, 100 means gating, <1 means upward compression)thresh: dB level threshold below which expansion kicks inrange: maximum amount of expansion in dB, as an attenuation: 20 and -20 both mean at most 20 dB of gain reduction (the sign is ignored)att: attack time = time constant (sec) coming out of expansionhold: hold time (sec)rel: release time = time constant (sec) going into expansionknee: a gradual increase in gain reduction around the threshold: above thresh+(knee/2) there is no gain reduction, below thresh-(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-range detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionmaxHold: the maximum hold time in samples, known at compile timeN: the number of channels of the gain computer, known at compile time
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
peak_expansion_gain_N_chan_db_test = (os.tosc(220)*lv, os.tosc(330)*lv) : co.peak_expansion_gain_N_chan_db(0.5, -40, 20, 0.05, 0.01, 0.02, 6, 0, 0.5, 2048, 2) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
peak_expansion_gain_N_chan_db_slider_test = (os.tosc(220)*lv, os.tosc(330)*lv) : co.peak_expansion_gain_N_chan_db(hslider("peak_expansion_gain_N_chan_db:strength", 0.5, 0, 1, 0.01), hslider("peak_expansion_gain_N_chan_db:thresh", -40, -60, 0, 0.1), hslider("peak_expansion_gain_N_chan_db:range", 20, 0, 60, 0.1), hslider("peak_expansion_gain_N_chan_db:att", 0.05, 0, 1, 0.001), hslider("peak_expansion_gain_N_chan_db:hold", 0.01, 0, 1, 0.001), hslider("peak_expansion_gain_N_chan_db:rel", 0.02, 0, 1, 0.001), hslider("peak_expansion_gain_N_chan_db:knee", 6, 0, 30, 0.1), hslider("peak_expansion_gain_N_chan_db:prePost", 0, 0, 1, 1), hslider("peak_expansion_gain_N_chan_db:link", 0.5, 0, 1, 0.01), 2048, 2) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
(co.)peak_expansion_gain_mono_db
Mono dynamic range expander gain computer with dB output. This is
the per-channel core of peak_expansion_gain_N_chan_db.
Usage
_ : peak_expansion_gain_mono_db(maxHold,strength,thresh,range,attack,hold,release,knee,prePost) : _
Where:
maxHold: the maximum hold time in samples, known at compile timestrength: strength of the expansion (0 = no expansion, 100 means gating, <1 means upward compression)thresh: dB level threshold below which expansion kicks inrange: maximum amount of expansion in dB, as an attenuation: 20 and -20 both mean at most 20 dB of gain reduction (the sign is ignored)attack: attack time = time constant (sec) coming out of expansionhold: hold time (sec)release: release time = time constant (sec) going into expansionknee: a gradual increase in gain reduction around the threshold: above thresh+(knee/2) there is no gain reduction, below thresh-(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-range detector
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
no = library("noises.lib");
peak_expansion_gain_mono_db_test = os.tosc(220)*lv : co.peak_expansion_gain_mono_db(2048, 0.5, -40, 20, 0.05, 0.01, 0.02, 6, 0) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
peak_expansion_gain_mono_db_hardknee_test = os.tosc(220)*lv : co.peak_expansion_gain_mono_db(2048, 0.5, -40, -20, 0.05, 0.01, 0.02, 0, 0) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
peak_expansion_gain_mono_db_slider_test = os.tosc(220)*lv : co.peak_expansion_gain_mono_db(2048, hslider("peak_expansion_gain_mono_db:strength", 0.5, 0, 1, 0.01), hslider("peak_expansion_gain_mono_db:thresh", -40, -60, 0, 0.1), hslider("peak_expansion_gain_mono_db:range", 20, 0, 60, 0.1), hslider("peak_expansion_gain_mono_db:attack", 0.05, 0, 1, 0.001), hslider("peak_expansion_gain_mono_db:hold", 0.01, 0, 1, 0.001), hslider("peak_expansion_gain_mono_db:release", 0.02, 0, 1, 0.001), hslider("peak_expansion_gain_mono_db:knee", 6, 0, 30, 0.1), hslider("peak_expansion_gain_mono_db:prePost", 0, 0, 1, 1)) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
peak_expansion_gain_mono_db_modulated_test = no.noise*e : co.peak_expansion_gain_mono_db(2048, 0.5, -40, -40, 0.001, 0.01, 0.001*pow(1000, tri), 6, 0) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
peak_expansion_gain_mono_db_jump_test = no.noise*e : co.peak_expansion_gain_mono_db(2048, 0.5, -40, -40, 0.001, 0.01, 0.001*pow(1000, sq), 6, 0) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); sq = ba.period(2*P) < P; };
(co.)expander_N_chan
Feed forward N channels dynamic range expander.
expander_N_chan is a standard Faust function.
Usage
si.bus(N) : expander_N_chan(strength,thresh,range,att,hold,rel,knee,prePost,link,meter,maxHold,N) : si.bus(N)
Where:
strength: strength of the expansion (0 = no expansion, 100 means gating, <1 means upward compression)thresh: dB level threshold below which expansion kicks inrange: maximum amount of expansion in dB, as an attenuation: 20 and -20 both mean at most 20 dB of gain reduction (the sign is ignored)att: attack time = time constant (sec) coming out of expansionhold: hold time (sec), at mostmaxHoldsamplesrel: release time = time constant (sec) going into expansionknee: a gradual increase in gain reduction around the threshold: above thresh+(knee/2) there is no gain reduction, below thresh-(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-range detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionmeter: a gain reduction meter. It can be implemented like so:meter = _<:(_, (ba.linear2db:max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;maxHold: the maximum hold time in samples, known at compile timeN: the number of channels of the expander, known at compile time
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
meter(x) = x;
expander_N_chan_test = (os.tosc(220)*lv, os.tosc(330)*lv) : co.expander_N_chan(0.5, -40, 20, 0.05, 0.02, 0.02, 6, 0, 0.5, meter, 4096, 2) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
expander_N_chan_slider_test = (os.tosc(220)*lv, os.tosc(330)*lv) : co.expander_N_chan(hslider("expander_N_chan:strength", 0.5, 0, 1, 0.01), hslider("expander_N_chan:thresh", -40, -60, 0, 0.1), hslider("expander_N_chan:range", 20, 0, 60, 0.1), hslider("expander_N_chan:att", 0.05, 0, 1, 0.001), hslider("expander_N_chan:hold", 0.02, 0, 1, 0.001), hslider("expander_N_chan:rel", 0.02, 0, 1, 0.001), hslider("expander_N_chan:knee", 6, 0, 30, 0.1), hslider("expander_N_chan:prePost", 0, 0, 1, 1), hslider("expander_N_chan:link", 0.5, 0, 1, 0.01), meter, 4096, 2) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
(co.)expanderSC_N_chan
Feed forward N channels dynamic range expander with sidechain.
expanderSC_N_chan is a standard Faust function.
Usage
si.bus(N) : expanderSC_N_chan(strength,thresh,range,att,hold,rel,knee,prePost,link,meter,maxHold,N,SCfunction,SCswitch,SCsignal) : si.bus(N)
Where:
strength: strength of the expansion (0 = no expansion, 100 means gating, <1 means upward compression)thresh: dB level threshold below which expansion kicks inrange: maximum amount of expansion in dB, as an attenuation: 20 and -20 both mean at most 20 dB of gain reduction (the sign is ignored)att: attack time = time constant (sec) coming out of expansionhold: hold time (sec), at mostmaxHoldsamplesrel: release time = time constant (sec) going into expansionknee: a gradual increase in gain reduction around the threshold: above thresh+(knee/2) there is no gain reduction, below thresh-(knee/2) there is the same gain reduction as without a knee, and in between there is a gradual increase in gain reductionprePost: places the level detector either at the input or after the gain computer; this turns it from a linear return-to-zero detector into a log domain return-to-range detectorlink: the amount of linkage between the channels: 0 = each channel is independent, 1 = all channels have the same amount of gain reductionmeter: a gain reduction meter. It can be implemented like so:meter = _<:(_, (ba.linear2db:max(maxGR):meter_group((hbargraph("[1][unit:dB][tooltip: gain reduction in dB]", maxGR, 0))))):attach;maxHold: the maximum hold time in samples, known at compile timeN: the number of channels of the expander, known at compile timeSCfunction: a function that get's placed before the level-detector, needs to have a single input and outputSCswitch: use either the regular audio input or the SCsignal as the input for the level detectorSCsignal: an audio signal, to be used as the input for the level detector when SCswitch is 1
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
meter(x) = x;
SCfunction(x) = x;
expanderSC_N_chan_test = (os.tosc(220), os.tosc(330)) : co.expanderSC_N_chan(0.5, -40, 20, 0.05, 0.02, 0.02, 6, 0, 0.5, meter, 4096, 2, SCfunction, 1, os.tosc(880)*lv) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
expanderSC_N_chan_slider_test = (os.tosc(220), os.tosc(330)) : co.expanderSC_N_chan(hslider("expanderSC_N_chan:strength", 0.5, 0, 1, 0.01), hslider("expanderSC_N_chan:thresh", -40, -60, 0, 0.1), hslider("expanderSC_N_chan:range", 20, 0, 60, 0.1), hslider("expanderSC_N_chan:att", 0.05, 0, 1, 0.001), hslider("expanderSC_N_chan:hold", 0.02, 0, 1, 0.001), hslider("expanderSC_N_chan:rel", 0.02, 0, 1, 0.001), hslider("expanderSC_N_chan:knee", 6, 0, 30, 0.1), hslider("expanderSC_N_chan:prePost", 0, 0, 1, 1), hslider("expanderSC_N_chan:link", 0.5, 0, 1, 0.01), meter, 4096, 2, SCfunction, hslider("expanderSC_N_chan:SCswitch", 1, 0, 1, 1), os.tosc(880)*lv) with { P = int(ma.SR/4); sq = ba.period(2*P) < P; lv = select2(sq, 0.001, 1); };
Lookahead Limiters
(co.)limiter_lad_N
N-channels lookahead limiter inspired by IOhannes Zmölnig's post, which is in turn based on the thesis by Peter Falkner "Entwicklung eines digitalen Stereo-Limiters mit Hilfe des Signalprozessors DSP56001". This version of the limiter uses a peak-holder with smoothed attack and release based on tau time constant filters.
It is also possible to use a time constant that is 2PI*tau by dividing
the attack and release times by 2PI. This time constant allows for
the amplitude profile to reach 1 - e^(-2PI) of the final
peak after the attack time. The input path can be delayed by the same
amount as the attack time to synchronise input and amplitude profile,
realising a system that is particularly effective as a colourless
(ideally) brickwall limiter.
Note that the effectiveness of the ceiling settings are dependent on the other parameters, especially the time constant used for the smoothing filters and the lookahead delay.
Similarly, the colourless characteristics are also dependent on attack, hold, and release times. Since fluctuations above ~15 Hz are perceived as timbral effects, [Vassilakis and Kendall 2010] it is reasonable to set the attack time to 1/15 seconds for a smooth amplitude modulation. On the other hand, the hold time can be set to the peak-to-peak period of the expected lowest frequency in the signal, which allows for minimal distortion of the low frequencies. The release time can then provide a perceptually linear and gradual gain increase determined by the user for any specific application.
The scaling factor for all the channels is determined by the loudest peak between them all, so that amplitude ratios between the signals are kept.
Usage
si.bus(N) : limiter_lad_N(N, LD, ceiling, attack, hold, release) : si.bus(N)
Where:
N: is the number of channels, known at compile-timeLD: is the lookahead delay in seconds, known at compile-timeceiling: is the linear amplitude output limitattack: is the attack time in secondshold: is the hold time in secondsrelease: is the release time in seconds
Example for a stereo limiter: limiter_lad_N(2, .01, 1, .01, .1, 1);
Test
co = library("compressors.lib");
os = library("oscillators.lib");
ba = library("basics.lib");
ma = library("maths.lib");
no = library("noises.lib");
limiter_lad_N_test = (os.tosc(440), os.tosc(660)) : co.limiter_lad_N(2, 0.01, 1, 0.01, 0.05, 0.2);
limiter_lad_N_slider_test = (os.tosc(440), os.tosc(660)) : co.limiter_lad_N(2, hslider("limiter_lad_N:LD", 0.01, 0, 0.1, 0.001), hslider("limiter_lad_N:ceiling", 1, 0, 2, 0.01), hslider("limiter_lad_N:attack", 0.01, 0, 1, 0.001), hslider("limiter_lad_N:hold", 0.05, 0, 1, 0.001), hslider("limiter_lad_N:release", 0.2, 0, 1, 0.001));
limiter_lad_N_modulated_test = par(i, 2, no.noises(2, i)*e) : par(i, 2, *(2)) : co.limiter_lad_N(2, 0.01, 0.5, 0.001, 0.01, 0.01*pow(100, tri)) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
limiter_lad_N_jump_test = par(i, 2, no.noises(2, i)*e) : par(i, 2, *(2)) : co.limiter_lad_N(2, 0.01, 0.5, 0.001, 0.01, 0.01*pow(100, sq)) with { e = pow(0.001, float(ba.period(Q))/Q); Q = int(ma.SR/4); P = int(ma.SR/10); sq = ba.period(2*P) < P; };
References
(co.)limiter_lad_mono
Specialised case of limiter_lad_N mono limiter.
Usage
_ : limiter_lad_mono(LD, ceiling, attack, hold, release) : _
Where:
LD: is the lookahead delay in seconds, known at compile-timeceiling: is the linear amplitude output limitattack: is the attack time in secondshold: is the hold time in secondsrelease: is the release time in seconds
Test
co = library("compressors.lib");
os = library("oscillators.lib");
limiter_lad_mono_test = os.tosc(440) : co.limiter_lad_mono(0.01, 1, 0.01, 0.05, 0.2);
limiter_lad_mono_slider_test = os.tosc(440) : co.limiter_lad_mono(hslider("limiter_lad_mono:LD", 0.01, 0, 0.1, 0.001), hslider("limiter_lad_mono:ceiling", 1, 0, 2, 0.01), hslider("limiter_lad_mono:attack", 0.01, 0, 1, 0.001), hslider("limiter_lad_mono:hold", 0.05, 0, 1, 0.001), hslider("limiter_lad_mono:release", 0.2, 0, 1, 0.001));
References
(co.)limiter_lad_stereo
Specialised case of limiter_lad_N stereo limiter.
Usage
_,_ : limiter_lad_stereo(LD, ceiling, attack, hold, release) : _,_
Where:
LD: is the lookahead delay in seconds, known at compile-timeceiling: is the linear amplitude output limitattack: is the attack time in secondshold: is the hold time in secondsrelease: is the release time in seconds
Test
co = library("compressors.lib");
os = library("oscillators.lib");
limiter_lad_stereo_test = (os.tosc(440), os.tosc(660)) : co.limiter_lad_stereo(0.01, 1, 0.01, 0.05, 0.2);
limiter_lad_stereo_slider_test = (os.tosc(440), os.tosc(660)) : co.limiter_lad_stereo(hslider("limiter_lad_stereo:LD", 0.01, 0, 0.1, 0.001), hslider("limiter_lad_stereo:ceiling", 1, 0, 2, 0.01), hslider("limiter_lad_stereo:attack", 0.01, 0, 1, 0.001), hslider("limiter_lad_stereo:hold", 0.05, 0, 1, 0.001), hslider("limiter_lad_stereo:release", 0.2, 0, 1, 0.001));
References
(co.)limiter_lad_quad
Specialised case of limiter_lad_N quadraphonic limiter.
Usage
si.bus(4) : limiter_lad_quad(LD, ceiling, attack, hold, release) : si.bus(4)
Where:
LD: is the lookahead delay in seconds, known at compile-timeceiling: is the linear amplitude output limitattack: is the attack time in secondshold: is the hold time in secondsrelease: is the release time in seconds
Test
co = library("compressors.lib");
os = library("oscillators.lib");
limiter_lad_quad_test = (os.tosc(220), os.tosc(330), os.tosc(440), os.tosc(550)) : co.limiter_lad_quad(0.01, 1, 0.01, 0.05, 0.2);
limiter_lad_quad_slider_test = (os.tosc(220), os.tosc(330), os.tosc(440), os.tosc(550)) : co.limiter_lad_quad(hslider("limiter_lad_quad:LD", 0.01, 0, 0.1, 0.001), hslider("limiter_lad_quad:ceiling", 1, 0, 2, 0.01), hslider("limiter_lad_quad:attack", 0.01, 0, 1, 0.001), hslider("limiter_lad_quad:hold", 0.05, 0, 1, 0.001), hslider("limiter_lad_quad:release", 0.2, 0, 1, 0.001));
References
(co.)limiter_lad_bw
Specialised case of limiter_lad_N and ready-to-use unit-amplitude mono
limiting function. This implementation, in particular, uses 2PI*tau
time constant filters for attack and release smoothing with
synchronised input and gain signals.
This function's best application is to be used as a brickwall limiter with the least colouring artefacts while keeping a not-so-slow release curve. Tests have shown that, given a pop song with 60 dB of amplification and a 0-dB-ceiling, the loudest peak recorded was ~0.38 dB.
Usage
_ : limiter_lad_bw : _
Test
co = library("compressors.lib");
os = library("oscillators.lib");
limiter_lad_bw_test = os.tosc(440) : co.limiter_lad_bw;
References
Multiband Compressors
(co.)xfer_ott
Model of Xfer Records' free OTT (measured: version 1.3.1), a three-band upward/downward compressor (the Ableton "OTT" preset lineage). Stereo in, stereo out, channels linked. Not affiliated with or endorsed by Xfer Records.
The input is split by series 4th-order Linkwitz-Riley crossovers at 88.3 Hz and 2.5 kHz. Each band has a per-sample envelope follower on the channels' mean square, an upward branch (a soft knee rising at about 4:1 below its threshold, with a gain cap), a downward branch (a soft knee into an infinite-ratio ceiling), a Depth-scaled makeup gain and a floor on the band's total gain; the three gained bands are summed.
Every constant was fitted to measurements of the plug-in binary. Static curves (one band active at a time, 0 to -150 dBFS, across Upward, Depth and threshold settings) match to 0.03-0.04 dB (median) and 1 dB at most. On stereo program material (guitar on one channel, drums on the other), as the error of the 50 ms envelope (median / 95th percentile) and the overall level, at 44.1 and 48 kHz:
- default settings (Time 100 %): 0.1 / 0.8-1.0 dB, level within 0.1 dB
- Depth 50 %: 0.1 / 0.6-0.7 dB; upward or downward branch alone: 0.1 / 0.2-1.0 dB; level within 0.1 dB
- Time 280 %: 0.4-0.5 / 1.3-1.4 dB; Time 640 %: 0.7-0.9 / 1.9-2.1 dB; level within 0.9 dB (the model is slightly quieter)
Sample rate: OTT counts part of its release in samples, so it releases faster at 96 kHz than at 48 kHz (its own envelope differs by 0.5 / 2.2 dB at default settings and 1.9 / 5.2 dB at Time 640 %). This model's release is in seconds and behaves at every sample rate like the plug-in at 48 kHz: at 96 kHz it is within 0.1-0.9 / 0.7-1.9 dB of the plug-in at 48 kHz.
Like the plug-in, the output can peak well above the input: the attack takes a few ms, and quiet bands sit at up to about +50 dB of upward gain, so a tone starting after silence overshoots its steady level by about 10 dB, and a sudden drop in level brings a brief burst. Follow it with a limiter where peaks matter.
Known divergences: the plug-in's steady-state gain on a sustained tone barely
depends on time (within 0.7 dB from 0 to 6.4); the model's moves by up to
1.0 dB over time 0-1 and up to 1.7 dB between 1 and 6.4. The plug-in's
"Clean XOV" crossover option is not modeled.
Usage
_,_ : xfer_ott(depth, time, ingain, outgain, upward, downward,
threshL, threshM, threshH, gainL, gainM, gainH,
bypUpL, bypUpM, bypUpH, bypDnL, bypDnM, bypDnH) : _,_
Where:
depth: compression depth (0-1; the plug-in's default is 1)time: release time scale (0-10, 1 = the plug-in's 100 %); it scales the release only, and the release is independent of the sample rateingain: input gain in dB (up to +19.1)outgain: output gain in dB (up to +19.1)upward: upward-compression strength (0-2, 1 = 100 %); it scales the upward slope in proportiondownward: downward-compression strength (0-2, 1 = 100 %); above 1 the downward ratio keeps steepening until it is infinite, which at depth 1 is already the case at 1threshL: low-band threshold (0-2, 1 = 100 %); 0 and 2 shift both of the band's knees by -23.0 and +23.0 dB. Raising it raises quiet signals more and lowers loud ones less, so at every input level the band's gain rises or holds, as on the plug-inthreshM: mid-band threshold (0-2, 1 = 100 %); 0 and 2 shift both of the band's knees by -23.7 and +23.7 dB. Raising it raises quiet signals more and lowers loud ones less, so at every input level the band's gain rises or holds, as on the plug-inthreshH: high-band threshold (0-2, 1 = 100 %); 0 and 2 shift both of the band's knees by -24.0 and +24.0 dB. Raising it raises quiet signals more and lowers loud ones less, so at every input level the band's gain rises or holds, as on the plug-ingainL: low-band output gain in dB (up to +6)gainM: mid-band output gain in dB (up to +6)gainH: high-band output gain in dB (up to +6)bypUpL: 1 bypasses the low band's upward branch, else 0bypUpM: 1 bypasses the mid band's upward branch, else 0bypUpH: 1 bypasses the high band's upward branch, else 0bypDnL: 1 bypasses the low band's downward branch, else 0bypDnM: 1 bypasses the mid band's downward branch, else 0bypDnH: 1 bypasses the high band's downward branch, else 0
Test
ba = library("basics.lib");
co = library("compressors.lib");
ma = library("maths.lib");
os = library("oscillators.lib");
xfer_ott_test = (os.tosc(220)*0.3, os.tosc(3000)*0.03)
: co.xfer_ott(1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
xfer_ott_slow_test = (os.tosc(220)*0.3, os.tosc(3000)*0.03)
: co.xfer_ott(0.5, 2.8, 3, -3, 1.5, 0.5, 0.8, 1.2, 1, 1, 0, -2, 0, 1, 0, 0, 0, 1);
// 3 Hz bursts, gated by a sample counter so that float and double switch together
xfer_ott_burst_test = (os.tosc(220)*0.3*g, os.tosc(3000)*0.03*(1 - g))
: co.xfer_ott(1, 2.8, 0, 0, 1, 1.5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
with { g = (ba.time % int(ma.SR / 3)) < int(ma.SR / 6); };
xfer_ott_slider_test = (os.tosc(220)*0.3, os.tosc(3000)*0.03)
: co.xfer_ott(hslider("xfer_ott:depth", 1, 0, 1, 0.01), hslider("xfer_ott:time", 1, 0, 10, 0.01), 0, 0,
hslider("xfer_ott:upward", 1, 0, 2, 0.01), hslider("xfer_ott:downward", 1, 0, 2, 0.01),
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
xfer_ott_modulated_test = (os.tosc(220)*0.3, os.tosc(3000)*0.03) : co.xfer_ott(tri, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) with { P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
xfer_ott_jump_test = (os.tosc(220)*0.3*g, os.tosc(3000)*0.03*(1 - g)) : co.xfer_ott(1, 10*sq, 0, 0, 1, 1.5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) with { P = int(ma.SR/10); sq = ba.period(2*P) < P; g = (ba.time % int(ma.SR / 3)) < int(ma.SR / 6); };