| 
							- // Copyright 2014 Olivier Gillet.
 - //
 - // Author: Olivier Gillet (ol.gillet@gmail.com)
 - //
 - // Permission is hereby granted, free of charge, to any person obtaining a copy
 - // of this software and associated documentation files (the "Software"), to deal
 - // in the Software without restriction, including without limitation the rights
 - // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 - // copies of the Software, and to permit persons to whom the Software is
 - // furnished to do so, subject to the following conditions:
 - // 
 - // The above copyright notice and this permission notice shall be included in
 - // all copies or substantial portions of the Software.
 - // 
 - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 - // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 - // THE SOFTWARE.
 - // 
 - // See http://creativecommons.org/licenses/MIT/ for more information.
 - //
 - // -----------------------------------------------------------------------------
 - //
 - // Compressor.
 - 
 - #include "streams/compressor.h"
 - 
 - // #include <cmath>
 - 
 - #include "stmlib/utils/dsp.h"
 - 
 - namespace streams {
 - 
 - using namespace stmlib;
 - 
 - // 256 LSB <=> 1.55dB
 - const int32_t kGainConstant = 1 / (1.55 / 6.0 * 65536.0 / 256.0) * 65536;
 - 
 - void Compressor::Init() {
 -   detector_ = 0;
 - }
 - 
 - /* static */
 - int32_t Compressor::Log2(int32_t value) {
 -   if (value <= 0) {
 -     value = 1;
 -   }
 -   int32_t log_value = 0;
 -   while (value >= 512) {
 -     value >>= 1;
 -     log_value += 65536;
 -   }
 -   while (value < 256) {
 -     value <<= 1;
 -     log_value -= 65536;
 -   }
 -   // Value is between 256 and 512, we can use the LUT.
 -   return log_value + lut_log2[value - 256];
 - }
 - 
 - /* static */
 - int32_t Compressor::Exp2(int32_t value) {
 -   int32_t num_shifts = 0;
 -   while (value >= 65536) {
 -     ++num_shifts;
 -     value -= 65536;
 -   }
 -   while (value < 0) {
 -     --num_shifts;
 -     value += 65536;
 -   }
 -   
 -   // Value is between 0 and 65535, we can use the LUT.
 -   int32_t a = lut_exp2[value >> 8];
 -   int32_t b = lut_exp2[(value >> 8) + 1];
 -   int32_t mantissa = a + ((b - a) * (value & 0xff) >> 8);
 -   return num_shifts >= 0 ? mantissa << num_shifts : mantissa >> -num_shifts;
 - }
 - 
 - /* static */
 - int32_t Compressor::Compress(
 -     int32_t squared_level,
 -     int32_t threshold,
 -     int32_t ratio,
 -     bool soft_knee) {
 -   int32_t level = (Log2(squared_level) >> 1) - 15 * 65536;  // 15-bit peak
 -   int32_t position = level - threshold;
 -   
 -   if (position < 0) {
 -     return 0;
 -   }
 -   
 -   int32_t attenuation = position - (position * ratio >> 8);
 -   if (attenuation < 65535 && soft_knee) {
 -     int32_t a = lut_soft_knee[attenuation >> 8];
 -     int32_t b = lut_soft_knee[(attenuation >> 8) + 1];
 -     int32_t soft_knee = a + ((b - a) * (attenuation & 0xff) >> 8);
 -     attenuation += \
 -         (soft_knee - attenuation) * ((65535 - attenuation) >> 1) >> 15;
 -   }
 -   return -attenuation;
 - }
 - 
 - void Compressor::Process(
 -     int16_t audio,
 -     int16_t excite,
 -     uint16_t* gain,
 -     uint16_t* frequency) {
 -   int32_t energy;
 -   int64_t error;
 -   
 -   // Detect the RMS level on the EXCITE input.
 -   energy = excite;
 -   energy *= energy;
 -   error = energy - sidechain_signal_detector_;
 -   if (error > 0) {
 -     sidechain_signal_detector_ += error;
 -   } else {
 -     // Decay time: 5s.
 -     sidechain_signal_detector_ += error * 14174 >> 31;
 -   }
 -   
 -   // If there is no signal on the "excite" input, disable sidechain and
 -   // compress by metering input.
 -   if (sidechain_signal_detector_ < (1024 * 1024)) {
 -     energy = audio;
 -     energy *= energy;
 -   }
 -   
 -   // Detect the RMS level on the EXCITE or AUDIO input - whichever active.
 -   error = energy - detector_;
 -   if (error > 0) {
 -     if (attack_coefficient_ == -1) {
 -       detector_ += error;
 -     } else {
 -       detector_ += error * attack_coefficient_ >> 31;
 -     }
 -   } else {
 -     detector_ += error * decay_coefficient_ >> 31;
 -   }
 -   
 -   int32_t g = Compress(detector_, threshold_, ratio_, soft_knee_);
 -   gain_reduction_ = g >> 3;
 -   g = kUnityGain + ((g + makeup_gain_) * kGainConstant >> 16);
 -   if (g > 65535) {
 -     g = 65535;
 -   }
 -   
 -   *gain = g;
 -   // float ogain = powf(10.0f, 1.55f / 20.0f * (g - kUnityGain) / 256.0f);
 -   // printf("%f %f\n", gain_reduction_ / 32768.0 * 24, 20 * logf(ogain) / logf(10.0f));
 -   *frequency = 65535;
 - }
 - 
 - }  // namespace streams
 
 
  |