Bela
Real-time, ultra-low-latency audio and sensor processing system for BeagleBone Black
Loading...
Searching...
No Matches
EnvelopeDetector.h
1#pragma once
2#include <math.h>
3/*
4 * \brief Envelope Detector Class.
5 * This detector uses one-pole IIR filters to extract the approximate envelope of an audio signal.
6 * Different modes of operation have been implemented to simulate detectors commonly used in compressors and other audio effects.
7 *
8 * Learn more:
9 * * Reiss, J. D., & McPherson, A. (2014). Audio effects: theory, implementation and application. CRC Press.
10 * * Pirkle, W. C. (2019). Designing Audio Effect Plugins in C++: For AAX, AU, and VST3 with DSP Theory. Routledge.
11 * * Giannoulis, D., Massberg, M., & Reiss, J. D. (2012). Digital dynamic range compressor design tutorial and analysis. Journal of the Audio Engineering Society, 60(6), 399-408.
12 *
13 * October 2021
14 * author: Adan L. Benito
15 */
16
17class EnvelopeDetector
18{
19 public:
20 const float kTcAnalog = log(1/M_E);
21 const float kTcDigital= log(0.01);
22
23 /*
24 * Type of time constant employed by envelope detector
25 */
26 typedef enum {
27 ANALOG = 0, /* < analog */
28 DIGITAL = 1 /* < digital */
29 } ConstantMode;
30
31 /*
32 * Type of peak detection strategy followed by the peak detector
33 */
34 typedef enum {
35 DECOUPLING = 0, /* < decoupling: detector with instantaneous attack filtered for release */
36 BRANCHING = 1 /* < branching: separated branches for attack and release */
37 } BranchingMode;
38
39 /*
40 * Type of level detection strategy employed to provide a smooth representation of signal's level
41 */
42 typedef enum {
43 PEAK = 0, /* < peak: detection performed over absolute peak values of the signal */
44 MS = 1, /* < mean square values of the input are used for detection */
45 RMS = 2, /* < root mean square values of the input are used for detecton */
46 PREPROCESSED = 3 /* < raw input is used for detection, assumes that a processed signal is feed into the detector */
47 } DetectionMode;
48
49 EnvelopeDetector();
50 /*
51 * Initialise envelope detector.
52 *
53 * @param attackTimeMs Attack time in milliseconds.
54 * @param releaseTimeMs Release time in milliseconds
55 * @param sampleRate Sampling frequency.
56 * @param constantMode Type of time constant employed by the detector
57 * @param branchingMode Type of peak detection strategy (branching or decoupling)
58 * @param detectionMode Type of level detection strategy
59 * @param smooth Boolean value indicating whether to use smooth release or not
60 */
61 EnvelopeDetector(float attackTimeMs, float releaseTimeMs, float sampleRate, unsigned int constantMode = ANALOG, unsigned int branchingMode = BRANCHING, unsigned int detectionMode = PEAK, bool smooth = true);
62 ~EnvelopeDetector();
63 /*
64 * \copydoc EnvelopeDetector::EnvelopeDetector(float, float, float, unsigned int, unsigned int, unsigned int, bool)
65 *
66 * @return 0 upon success, error otherwise
67 */
68 int setup(float attackTimeMs, float releaseTimeMs, float sampleRate, unsigned int constantMode = ANALOG, unsigned int branchingMode = BRANCHING, unsigned int detectionMode = PEAK, bool smooth = true);
69 int cleanup();
70
71 /*
72 * Process input signal acording to detector's parameters and return envelope.
73 *
74 * @return Computed envelope
75 */
76 float process(float input);
77 /*
78 * Set attack time
79 *
80 * @param attackTimeMs Attack time (milliseconds)
81 */
82 void setAttackTime(float attackTimeMs);
83 /*
84 * Get attack time
85 *
86 * @returns Attack time in milliseconds
87 */
88 float getAttackTime() { return _attackTimeMs; };
89 /*
90 * Set release time
91 *
92 * @param releaseTimeMs Release time (milliseconds)
93 */
94 void setReleaseTime(float releaseTimeMs);
95 /*
96 * Get release time
97 *
98 * @returns Release time in milliseconds
99 */
100 float getReleaseTime() { return _releaseTimeMs; };
101 /*
102 * Set mode of operation for time constant
103 *
104 * @param mode Mode of operation for time constant (\see EnvelopeDetector::ConstantMode)
105 */
106 void setConstantMode(unsigned int mode);
107 /*
108 * Get time constant mode of operation
109 */
110 unsigned int getConstantMode() { return _constantMode; };
111 /*
112 * Set branching mode
113 *
114 * @param mode Branching mode (\see EnvelopeDetector::BranchingMode)
115 */
116 void setBranchingMode(unsigned int mode);
117 /*
118 * Get branching mode
119 */
120 unsigned int getBranchingMOde() { return _branchingMode; };
121 /*
122 * Set envelope detection mode
123 *
124 * @param mode Detection mode (\see EnvelopeDetector::DetectionMode)
125 */
126 void setDetectionMode(unsigned int mode);
127 /*
128 * Get envelope detection mode
129 */
130 unsigned getDetectionMode() { return _detectionMode; };
131
132 /*
133 * Set smooth release operation for detector
134 *
135 * @param isSmooth Boolean, if true then use smooth release.
136 */
137 void setSmooth(bool isSmooth);
138 /*
139 * Retrieve whether smooth operation is being used or not
140 */
141 bool getSmooth() { return _smooth; };
142
143 private:
144 float _fs = 0.0; // Sampling frequency
145 float _tc = kTcAnalog; // Time contstant
146
147 float _attackTimeMs = 0.0; // Attack time in milliseconds
148 float _releaseTimeMs = 0.0; // Release time in milliseconds
149
150 float _tConstantAttack = 0.0; // Attack time constant
151 float _tConstantRelease = 0.0; // Release time constant
152
153 float _fastPeakEstimation = 0.0; // Only for DECOUPLING detector
154 float _envelope = 0.0; // Envelope value
155
156 unsigned int _constantMode = ANALOG; // Time constant mode
157 unsigned int _branchingMode = BRANCHING; // Branching mode
158 unsigned int _detectionMode = PEAK; // Detection mode
159
160 bool _smooth = true; // Flag for smooth operation
161
162 /*
163 * Compute time constant for given time in milliseconds
164 *
165 * @param timeMs Time in milliseconds
166 */
167 double computeTimeConstant(float timeMs);
168 /*
169 * Reset detector state
170 */
171 void resetState();
172};