Logo Search packages:      
Sourcecode: caps version File versions

Compress.cc

/*
      Compress.cc
      
      Copyright 2004 Tim Goetze <tim@quitte.de>
      
      http://quitte.de/dsp/

      mono compressor suitable for solo instruments. adaptation of Steve
      Harris' 'sc1' unit, with minor tweaks: table lookup for attack and
      release time to frames mapping replaced with exp. port order changed.
*/
/*
      This program is free software; you can redistribute it and/or
      modify it under the terms of the GNU General Public License
      as published by the Free Software Foundation; either version 2
      of the License, or (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      02111-1307, USA or point your web browser to http://www.gnu.org.
*/

#include "basics.h"

#include "Compress.h"
#include "Descriptor.h"

void
Compress::init (double _fs)
{
      fs = _fs;
}

template <sample_func_t F>
void
Compress::one_cycle (int frames)
{
      d_sample * s = ports[0];

      d_sample range = DSP::db2lin (*ports[1]); 
      d_sample ratio = (*ports[2] - 1) / *ports[2];

      /* sc1 has lookup tables here, and they're only 40 % used (400 ms/1 s). 
       * thus, sc1's attack/release controls are a bit coarse due to truncation 
       * error. calling exp() once per cycle doesn't seem too expensive. 
       *
       * besides, i have a suspicion that the attack and release parameters
       * don't work like they should. if they, as the code suggests, control
       * an exponential envelope fade, pow (.5, n_frames) or something like
       * that seems more appropriate. so ...
       *
       * TODO: check whether these parameters work like they should, try pow()
       */
      double ga = exp (-1 / (fs * *ports[3])); 
      double gr = exp (-1 / (fs * *ports[4]));

      d_sample threshold = *ports[5];
      d_sample knee = *ports[6];

      d_sample * d = ports[7];

      d_sample knee0 = DSP::db2lin (threshold - knee);
      d_sample knee1 = DSP::db2lin (threshold + knee);

      d_sample ef_a = ga * .25;
      d_sample ef_ai = 1 - ef_a;
      
      for (int i = 0; i < frames; ++i)
      {
            sum += s[i] * s[i];

            if (amp > env)
                  env = env * ga + amp * (1 - ga);
            else
                  env = env * gr + amp * (1 - gr);

            if ((count++ & 3) == 3)
            {
                  amp = rms.process (sum * .25);
                  sum = 0;
                  
                  if (env < knee0)
                        gain_t = 1;
                  else if (env < knee1)
                  {
                        float x = -(threshold - knee - DSP::lin2db (env)) / knee;
                        gain_t = DSP::db2lin (-knee * ratio * x * x * 0.25f);
                  }
                  else
                        gain_t = DSP::db2lin ((threshold - DSP::lin2db (env)) * ratio);
            }

        gain = gain * ef_a + gain_t * ef_ai;

            F (d, i, s[i] * gain * range, adding_gain);
      }
}

/* //////////////////////////////////////////////////////////////////////// */

PortInfo
Compress::port_info [] =
{
      {
            "in",
            INPUT | AUDIO,
            {BOUNDED, -1, 1}
      }, {
            "gain (dB)",
            INPUT | CONTROL,
            {BOUNDED | DEFAULT_LOW, 0, 24}
      }, {
            "ratio (1:n)",
            INPUT | CONTROL,
            {BOUNDED | DEFAULT_MIN, 1, 10}
      }, {
            "attack (s)",
            INPUT | CONTROL,
            {BOUNDED | DEFAULT_MIN, .001, 1}
      }, {
            "release (s)",
            INPUT | CONTROL,
            {BOUNDED | DEFAULT_MID, .001, 1}
      }, {
            "threshold (dB)",
            INPUT | CONTROL,
            {BOUNDED | DEFAULT_0, -30, 400}
      }, {
            "knee radius (dB)",
            INPUT | CONTROL,
            {BOUNDED | DEFAULT_LOW, 1, 10}
      }, {
            "out",
            OUTPUT | AUDIO,
            {0}
      }
};

Descriptor<Compress>::Descriptor<Compress>()
{
      UniqueID = 1772;
      Label = "Compress";
      Properties = HARD_RT;

      Name = "Mono compressor suitable for musical instruments";
      Maker = "Tim Goetze <tim@quitte.de>, Steve Harris <steve@plugin.org.uk>";
      Copyright = "GPL, 2004";

      /* fill port info and vtable */
      autogen();
}


Generated by  Doxygen 1.6.0   Back to index