1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef LE_FX_ENGINE_DSP_CORE_DYNAMIC_RANGE_COMPRESSION_H_
17#define LE_FX_ENGINE_DSP_CORE_DYNAMIC_RANGE_COMPRESSION_H_
18
19#include "common/core/types.h"
20#include "common/core/math.h"
21#include "dsp/core/basic.h"
22#include "dsp/core/interpolation.h"
23
24//#define LOG_NDEBUG 0
25#include <cutils/log.h>
26
27
28namespace le_fx {
29
30// An adaptive dynamic range compression algorithm. The gain adaptation is made
31// at the logarithmic domain and it is based on a Branching-Smooth compensated
32// digital peak detector with different time constants for attack and release.
33class AdaptiveDynamicRangeCompression {
34 public:
35    AdaptiveDynamicRangeCompression();
36
37    // Initializes the compressor using prior information. It assumes that the
38    // input signal is speech from high-quality recordings that is scaled and then
39    // fed to the compressor. The compressor is tuned according to the target gain
40    // that is expected to be applied.
41    //
42    // Target gain receives values between 0.0 and 10.0. The knee threshold is
43    // reduced as the target gain increases in order to fit the increased range of
44    // values.
45    //
46    // Values between 1.0 and 2.0 will only mildly affect your signal. Higher
47    // values will reduce the dynamic range of the signal to the benefit of
48    // increased loudness.
49    //
50    // If nothing is known regarding the input, a `target_gain` of 1.0f is a
51    // relatively safe choice for many signals.
52    bool Initialize(float target_gain, float sampling_rate);
53
54  // A fast version of the algorithm that uses approximate computations for the
55  // log(.) and exp(.).
56  float Compress(float x);
57
58  // Stereo channel version of the compressor
59  void Compress(float *x1, float *x2);
60
61  // This version is slower than Compress(.) but faster than CompressSlow(.)
62  float CompressNormalSpeed(float x);
63
64  // A slow version of the algorithm that is easier for further developement,
65  // tuning and debugging
66  float CompressSlow(float x);
67
68  // Sets knee threshold (in decibel).
69  void set_knee_threshold(float decibel);
70
71  // Sets knee threshold via the target gain using an experimentally derived
72  // relationship.
73  void set_knee_threshold_via_target_gain(float target_gain);
74
75 private:
76  // The minimum accepted absolute input value and it's natural logarithm. This
77  // is to prevent numerical issues when the input is close to zero
78  static const float kMinAbsValue;
79  static const float kMinLogAbsValue;
80  // Fixed-point arithmetic limits
81  static const float kFixedPointLimit;
82  static const float kInverseFixedPointLimit;
83  // The default knee threshold in decibel. The knee threshold defines when the
84  // compressor is actually starting to compress the value of the input samples
85  static const float kDefaultKneeThresholdInDecibel;
86  // The compression ratio is the reciprocal of the slope of the line segment
87  // above the threshold (in the log-domain). The ratio controls the
88  // effectiveness of the compression.
89  static const float kCompressionRatio;
90  // The attack time of the envelope detector
91  static const float kTauAttack;
92  // The release time of the envelope detector
93  static const float kTauRelease;
94
95  float sampling_rate_;
96  // the internal state of the envelope detector
97  float state_;
98  // the latest gain factor that was applied to the input signal
99  float compressor_gain_;
100  // attack constant for exponential dumping
101  float alpha_attack_;
102  // release constant for exponential dumping
103  float alpha_release_;
104  float slope_;
105  // The knee threshold
106  float knee_threshold_;
107  float knee_threshold_in_decibel_;
108  // This interpolator provides the function that relates target gain to knee
109  // threshold.
110  sigmod::InterpolatorLinear<float> target_gain_to_knee_threshold_;
111
112  LE_FX_DISALLOW_COPY_AND_ASSIGN(AdaptiveDynamicRangeCompression);
113};
114
115}  // namespace le_fx
116
117#include "dsp/core/dynamic_range_compression-inl.h"
118
119#endif  // LE_FX_ENGINE_DSP_CORE_DYNAMIC_RANGE_COMPRESSION_H_
120