Compress.cc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. Compress.cc
  3. Copyright 2004-7 Tim Goetze <tim@quitte.de>
  4. http://quitte.de/dsp/
  5. mono compressor suitable for solo instruments. adaptation of Steve
  6. Harris' 'sc1' unit, with minor tweaks: table lookup for attack and
  7. release time to frames mapping replaced with exp. port order changed.
  8. */
  9. /*
  10. This program is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU General Public License
  12. as published by the Free Software Foundation; either version 2
  13. of the License, or (at your option) any later version.
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. GNU General Public License for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  21. 02111-1307, USA or point your web browser to http://www.gnu.org.
  22. */
  23. #include "basics.h"
  24. #include "Compress.h"
  25. #include "Descriptor.h"
  26. template <sample_func_t F>
  27. void
  28. Compress::one_cycle (int frames)
  29. {
  30. sample_t * s = ports[0];
  31. sample_t range = DSP::db2lin (getport(1));
  32. sample_t ratio = (*ports[2] - 1) / getport(2);
  33. /* sc1 has lookup tables here, and they're only 40 % used (400 ms/1 s).
  34. * thus, sc1's attack/release controls are a bit coarse due to truncation
  35. * error. calling exp() once per cycle doesn't seem too expensive.
  36. *
  37. * besides, i have a suspicion that the attack and release parameters
  38. * don't work like they should. if they, as the code suggests, control
  39. * an exponential envelope fade, pow (.5, n_frames) or something like
  40. * that seems more appropriate. so ...
  41. *
  42. * TODO: check whether these parameters work like they should, try pow()
  43. */
  44. double ga = exp (-1 / (fs * getport(3)));
  45. double gr = exp (-1 / (fs * getport(4)));
  46. sample_t threshold = getport(5);
  47. sample_t knee = getport(6);
  48. sample_t * d = ports[7];
  49. sample_t knee0 = DSP::db2lin (threshold - knee);
  50. sample_t knee1 = DSP::db2lin (threshold + knee);
  51. sample_t ef_a = ga * .25;
  52. sample_t ef_ai = 1 - ef_a;
  53. for (int i = 0; i < frames; ++i)
  54. {
  55. sum += s[i] * s[i];
  56. if (amp > env)
  57. env = env * ga + amp * (1 - ga);
  58. else
  59. env = env * gr + amp * (1 - gr);
  60. if ((count++ & 3) == 3)
  61. {
  62. amp = rms.process (sum * .25);
  63. sum = 0;
  64. if (env < knee0)
  65. gain_t = 1;
  66. else if (env < knee1)
  67. {
  68. float x = -(threshold - knee - DSP::lin2db (env)) / knee;
  69. gain_t = DSP::db2lin (-knee * ratio * x * x * 0.25f);
  70. }
  71. else
  72. gain_t = DSP::db2lin ((threshold - DSP::lin2db (env)) * ratio);
  73. }
  74. gain = gain * ef_a + gain_t * ef_ai;
  75. F (d, i, s[i] * gain * range, adding_gain);
  76. }
  77. }
  78. /* //////////////////////////////////////////////////////////////////////// */
  79. PortInfo
  80. Compress::port_info [] =
  81. {
  82. {
  83. "in",
  84. INPUT | AUDIO,
  85. {BOUNDED, -1, 1}
  86. }, {
  87. "gain (dB)",
  88. INPUT | CONTROL,
  89. {BOUNDED | DEFAULT_LOW, 0, 24}
  90. }, {
  91. "ratio (1:n)",
  92. INPUT | CONTROL,
  93. {BOUNDED | DEFAULT_MIN, 1, 10}
  94. }, {
  95. "attack (s)",
  96. INPUT | CONTROL,
  97. {BOUNDED | DEFAULT_MIN, .001, 1}
  98. }, {
  99. "release (s)",
  100. INPUT | CONTROL,
  101. {BOUNDED | DEFAULT_MID, .001, 1}
  102. }, {
  103. "threshold (dB)",
  104. INPUT | CONTROL,
  105. {BOUNDED | DEFAULT_0, -30, 400}
  106. }, {
  107. "knee radius (dB)",
  108. INPUT | CONTROL,
  109. {BOUNDED | DEFAULT_LOW, 1, 10}
  110. }, {
  111. "out",
  112. OUTPUT | AUDIO,
  113. {0}
  114. }
  115. };
  116. template <> void
  117. Descriptor<Compress>::setup()
  118. {
  119. UniqueID = 1772;
  120. Label = "Compress";
  121. Properties = HARD_RT;
  122. Name = CAPS "Compress - Mono compressor";
  123. Maker = "Tim Goetze <tim@quitte.de>, Steve Harris <steve@plugin.org.uk>";
  124. Copyright = "GPL, 2004-7";
  125. /* fill port info and vtable */
  126. autogen();
  127. }