-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathAudioEffectCompWDRC_F32.h
166 lines (135 loc) · 6.7 KB
/
AudioEffectCompWDRC_F32.h
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
* AudioEffectCompWDR_F32: Wide Dynamic Rnage Compressor
*
* Created: Chip Audette (OpenAudio) Feb 2017
* Derived From: WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro
* As of Feb 2017, CHAPRO license is listed as "Creative Commons?"
*
* MIT License. Use at your own risk.
*
*/
#ifndef _AudioEffectCompWDRC_F32
#define _AudioEffectCompWDRC_F32
class AudioCalcGainWDRC_F32; //forward declared. Actually defined in later header file, but I need this here to avoid circularity
#include <Arduino.h>
#include <AudioStream_F32.h>
#include <arm_math.h>
#include <AudioCalcEnvelope_F32.h>
#include <AudioCalcGainWDRC_F32.h> //has definition of CHA_WDRC
#include "BTNRH_WDRC_Types.h"
//#include "utility/textAndStringUtils.h"
class AudioEffectCompWDRC_F32 : public AudioStream_F32
{
//GUI: inputs:1, outputs:1 //this line used for automatic generation of GUI node
//GUI: shortName: CompressWDRC
public:
AudioEffectCompWDRC_F32(void): AudioStream_F32(1,inputQueueArray) { //need to modify this for user to set sample rate
setSampleRate_Hz(AUDIO_SAMPLE_RATE);
setDefaultValues();
}
AudioEffectCompWDRC_F32(AudioSettings_F32 settings): AudioStream_F32(1,inputQueueArray) { //need to modify this for user to set sample rate
setSampleRate_Hz(settings.sample_rate_Hz);
setDefaultValues();
}
//here is the method called automatically by the audio library
void update(void) {
//receive the input audio data
audio_block_f32_t *block = AudioStream_F32::receiveReadOnly_f32();
if (!block) return;
//allocate memory for the output of our algorithm
audio_block_f32_t *out_block = AudioStream_F32::allocate_f32();
if (!out_block) return;
Serial.print("data37= "); Serial.print(block->data[37], 6);
//do the algorithm
compress(block->data, out_block->data, block->length);
// transmit the block and release memory
AudioStream_F32::transmit(out_block); // send the FIR output
AudioStream_F32::release(out_block);
AudioStream_F32::release(block);
}
//here is the function that does all the work
//void cha_agc_channel(float *input, float *output, int cs) {
// //compress(input, output, cs, &prev_env,
// // CHA_DVAR.alfa, CHA_DVAR.beta, CHA_DVAR.tkgain, CHA_DVAR.tk, CHA_DVAR.cr, CHA_DVAR.bolt, CHA_DVAR.maxdB);
// compress(input, output, cs);
//}
//void compress(float *x, float *y, int n, float *prev_env,
// float &alfa, float &beta, float &tkgn, float &tk, float &cr, float &bolt, float &mxdB)
void compress(float *x, float *y, int n)
//x, input, audio waveform data
//y, output, audio waveform data after compression
//n, input, number of samples in this audio block
{
// find smoothed envelope
audio_block_f32_t *envelope_block = AudioStream_F32::allocate_f32();
if (!envelope_block) return;
calcEnvelope.smooth_env(x, envelope_block->data, n);
Serial.print(" Envelope37= "); Serial.print(envelope_block->data[37], 6);
//float *xpk = envelope_block->data; //get pointer to the array of (empty) data values
//calculate gain
audio_block_f32_t *gain_block = AudioStream_F32::allocate_f32();
if (!gain_block) return;
calcGain.calcGainFromEnvelope(envelope_block->data, gain_block->data, n);
Serial.print(" Gain37= "); Serial.println(envelope_block->data[37], 6);
//apply gain
arm_mult_f32(x, gain_block->data, y, n);
// release memory
AudioStream_F32::release(envelope_block);
AudioStream_F32::release(gain_block);
}
void setDefaultValues(void) {
//set default values...configure as limitter
BTNRH_WDRC::CHA_WDRC gha = {
5.0f, // attack time (ms)
50.0f, // release time (ms)
24000.0f, // fs, sampling rate (Hz), THIS IS IGNORED!
115.0f, // maxdB, maximum signal (dB SPL)...assumed SPL for full-scale input signal
0.0f, // tkgain, compression-start gain (dB)
55.0f, // tk, compression-start kneepoint (dB SPL)
1.0f, // cr, compression ratio (set to 1.0 to defeat)
100.0f // bolt, broadband output limiting threshold (ie, the limiter. SPL. 10:1 comp ratio)
};
setParams_from_CHA_WDRC(&gha);
}
//set all of the parameters for the compressor using the CHA_WDRC structure
//assumes that the sample rate has already been set!!!
void setParams_from_CHA_WDRC(BTNRH_WDRC::CHA_WDRC *gha) {
//configure the envelope calculator...assumes that the sample rate has already been set!
calcEnvelope.setAttackRelease_msec(gha->attack,gha->release); //these are in milliseconds
//configure the compressor
calcGain.setParams_from_CHA_WDRC(gha);
}
//set all of the user parameters for the compressor
//assumes that the sample rate has already been set!!!
void setParams(float attack_ms, float release_ms, float maxdB, float tkgain, float comp_ratio, float tk, float bolt) {
//configure the envelope calculator...assumes that the sample rate has already been set!
calcEnvelope.setAttackRelease_msec(attack_ms,release_ms);
//configure the WDRC gains
calcGain.setParams(maxdB, tkgain, comp_ratio, tk, bolt);
}
void setSampleRate_Hz(const float _fs_Hz) {
//pass this data on to its components that care
given_sample_rate_Hz = _fs_Hz;
calcEnvelope.setSampleRate_Hz(_fs_Hz);
}
void setAttackRelease_msec(const float atk_msec, const float rel_msec) {
calcEnvelope.setAttackRelease_msec(atk_msec, rel_msec);
}
void setKneeLimiter_dBSPL(float _bolt) { calcGain.setKneeLimiter_dBSPL(_bolt); }
void setKneeLimiter_dBFS(float _bolt_dBFS) { calcGain.setKneeLimiter_dBFS(_bolt_dBFS); }
void setGain_dB(float _gain_dB) { calcGain.setGain_dB(_gain_dB); } //gain at start of compression
void setKneeCompressor_dBSPL(float _tk) { calcGain.setKneeCompressor_dBSPL(_tk); }
void setKneeCompressor_dBFS(float _tk_dBFS) { calcGain.setKneeCompressor_dBFS(_tk_dBFS); }
void setCompRatio(float _cr) { calcGain.setCompRatio(_cr); }
void setMaxdB(float _maxdB) { calcGain.setMaxdB(_maxdB); };
float getCurrentLevel_dB(void) { return AudioCalcGainWDRC_F32::db2(calcEnvelope.getCurrentLevel()); } //this is 20*log10(abs(signal)) after the envelope smoothing
float getGain_dB(void) { return calcGain.getGain_dB(); } //returns the linear gain of the system
float getCurrentGain(void) { return calcGain.getCurrentGain(); }
float getCurrentGain_dB(void) { return calcGain.getCurrentGain_dB(); }
AudioCalcEnvelope_F32 calcEnvelope;
AudioCalcGainWDRC_F32 calcGain;
private:
audio_block_f32_t *inputQueueArray[1];
float given_sample_rate_Hz;
};
#endif