summaryrefslogtreecommitdiffstats
path: root/src/engine/enginesidechaincompressor.h
blob: bc7d030c652d4c86115c72a21e1f7e7970830596 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#pragma once

#include "util/types.h"

class EngineSideChainCompressor {
  public:
    EngineSideChainCompressor(const QString& group);
    virtual ~EngineSideChainCompressor() { };

    void setParameters(CSAMPLE threshold, CSAMPLE strength,
                       unsigned int attack_time, unsigned int decay_time) {
        // TODO(owilliams): There is a race condition here because the parameters
        // are not updated atomically.  This function should instead take a
        // struct.
        m_threshold = threshold;
        m_strength = strength;
        m_attackTime = attack_time;
        m_decayTime = decay_time;
        calculateRates();
    }

    void setThreshold(CSAMPLE threshold) {
        m_threshold = threshold;
        calculateRates();
    }

    void setStrength(CSAMPLE strength) {
        m_strength = strength;
        calculateRates();
    }

    void setAttackTime(unsigned int attack_time) {
        m_attackTime = attack_time;
        calculateRates();
    }

    void setDecayTime(unsigned int decay_time) {
        m_decayTime = decay_time;
        calculateRates();
    }

    /// Forces the above threshold flag to the given value without calculations
    void setAboveThreshold(bool value);

    // Every loop, before calling process, first call processKey to feed
    // the compressor the input key signal.  It is safe to call this function
    // multiple times for multiple keys, however they will not be summed together
    // so compression will not be triggered unless at least one buffer would
    // have triggered alone.
    void processKey(const CSAMPLE* pIn, const int iBufferSize);

    // Calculates a new gain value based on the current compression ratio
    // over the given number of frames and whether the current input is above threshold.
    double calculateCompressedGain(int frames);

  private:
    // Update the attack and decay rates.
    void calculateRates();

    // The current ratio the signal is being compressed.  This is the same as m_strength
    // when the compressor is at maximum engagement (not attacking or decaying).
    CSAMPLE m_compressRatio;

    // True if the input signal is above the threshold.
    bool m_bAboveThreshold;

    // The sample value above which the compressor is triggered.
    CSAMPLE m_threshold;

    // The largest ratio the signal can be compressed.
    CSAMPLE m_strength;

    // The length of time, in frames (samples/2), until maximum compression is reached.
    unsigned int m_attackTime;

    // The length of time, in frames, until compression is completely off.
    unsigned int m_decayTime;

    // These are the delta compression values per sample based on the strengths and timings.
    CSAMPLE m_attackPerFrame;
    CSAMPLE m_decayPerFrame;
};