-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathf670l_StereoProcessor.hpp
174 lines (160 loc) · 7.57 KB
/
f670l_StereoProcessor.hpp
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
166
167
168
169
170
171
172
173
174
//==============================================================================
/**
Wavechild 670
-------------
Wave digital filter based emulation of a famous 1950's tube stereo limiter
WDF++ based source code by Maxime Coorevits (Nord, France) in 2013
Some part are inspired by the Peter Raffensperger project: Wavechild670,
a command line with python WDF generator that produce C++ code of the circuit.
Major restructuration:
----------------------
* WDF++ based project (single WDF++.hpp file)
* full C++, zero-dependencies except JUCE (core API, AudioProcessor).
* JUCE Plugin wrapper processor (VST, AU ...)
* Photo-Realistic GUI
Reference:
----------
Toward a Wave Digital Filter Model of the Fairchild 670 Limiter,
Raffensperger, P. A., (2012).
Proc. of the 15th International Conference on Digital Audio Effects (DAFx-12),
York, UK, September 17-21, 2012.
Note:
-----
Fairchild (R) a registered trademark of Avid Technology, Inc.,
which is in no way associated or affiliated with the author.
**/
//==============================================================================
#ifndef __F670L_STEREO_PROCESSOR_HPP_9D267F6C__
#define __F670L_STEREO_PROCESSOR_HPP_9D267F6C__
//==============================================================================
#include "f670l_SignalAmplifier.hpp"
#include "f670l_LevelTimeConstant.hpp"
#include "f670l_SidechainAmplifier.hpp"
//==============================================================================
namespace Wavechild670 {
//==============================================================================
#define SQRT_2 sqrt(2.0)
//==============================================================================
template <typename T>
class StereoProcessor
{
public:
StereoProcessor ()
: Fs (44100.0), gain (1.0),
//-------------------------
A (0.0), B (0.0),
capA (0.0), capB (0.0),
levelA (1.0), levelB (1.0),
thresholdA (1.0), thresholdB (1.0),
tcA (2), tcB (2),
//-------------------------
hardclipout (true),
feedback (false),
midside (false),
linked (true)
{}
//----------------------------------------------------------------------
void init (T sampleRate)
{
Fs = sampleRate;
//------------------------------------------------------------------
signalAmpA = new SignalAmplifier<double> (Fs);
signalAmpB = new SignalAmplifier<double> (Fs);
//------------------------------------------------------------------
sidechainAmpA = new SidechainAmplifier<double> (Fs);
sidechainAmpB = new SidechainAmplifier<double> (Fs);
//------------------------------------------------------------------
timeConstantA = new LevelTimeConstant<double> (Fs);
timeConstantB = new LevelTimeConstant<double> (Fs);
//------------------------------------------------------------------
timeConstantA->parameters (Fs, tcA);
timeConstantB->parameters (Fs, tcB);
//------------------------------------------------------------------
capA = A = 0.0;
capB = B = 0.0;
//------------------------------------------------------------------
warmup ();
}
//----------------------------------------------------------------------
void parameters (const int tA, const int tB)
{
tcA = tA; timeConstantA->parameters (Fs, tcA);
tcB = tB; timeConstantB->parameters (Fs, tcB);
}
//----------------------------------------------------------------------
inline T sidechain (T VscA, T VscB)
{
T IscA = sidechainAmpA->process (VscA, capA);
T IscB = sidechainAmpB->process (VscB, capB);
if (linked)
{
T IscT = (IscA + IscB) * 0.5;
T Ax = timeConstantA->process (IscT);
T Bx = timeConstantB->process (IscT);
capA =
capB = (Ax + Bx) * 0.5;
}
else
{
capA = timeConstantA->process (IscA);
capB = timeConstantA->process (IscB);
}
}
//----------------------------------------------------------------------
inline T hardclip (T x, T min, T max) { return (x < min) ? min
: (x > max) ? max
: x; }
//----------------------------------------------------------------------
inline void process (float *left, float *right)
{
A = (midside) ? (T)((left[0] + left[0] ) / SQRT_2) : left[0];
B = (midside) ? (T)((right[0] - right[0]) / SQRT_2) : right[0];
A *= levelA;
B *= levelB;
if (!feedback) sidechain (A, B);
A = signalAmpA->process (A, capA);
B = signalAmpB->process (B, capB);
if ( feedback) sidechain (A, B);
A = (midside) ? (A + B) / SQRT_2 : A;
B = (midside) ? (A - B) / SQRT_2 : B;
A *= gain;
B *= gain;
A = (hardclipout) ? hardclip(A, -1.0, 1.0) : A;
B = (hardclipout) ? hardclip(B, -1.0, 1.0) : B;
left[0] = (float)A;
right[0] = (float)B;
}
//----------------------------------------------------------------------
void warmup (T timeInSec = 0.5)
{
long i, samples = (long) (timeInSec*Fs)/2;
i = 0; for (; i < samples; ++i) { signalAmpA->process (0.0, capA);
signalAmpB->process (0.0, capB); }
i = 0; for (; i < samples; ++i) { T VscA = signalAmpA->process (0.0, capA);
T VscB = signalAmpB->process (0.0, capB);
sidechain (VscA, VscB); }
}
//----------------------------------------------------------------------
T Fs; // samplerate
//----------------------------------------------------------------------
int tcA, tcB;
bool hardclipout, midside, linked, feedback;
T A, B, capA, capB, levelA, levelB, thresholdA, thresholdB, gain;
//----------------------------------------------------------------------
ScopedPointer<SignalAmplifier<T>> signalAmpA;
ScopedPointer<SignalAmplifier<T>> signalAmpB;
//----------------------------------------------------------------------
ScopedPointer<LevelTimeConstant<T>> timeConstantA;
ScopedPointer<LevelTimeConstant<T>> timeConstantB;
//----------------------------------------------------------------------
ScopedPointer<SidechainAmplifier<T>> sidechainAmpA;
ScopedPointer<SidechainAmplifier<T>> sidechainAmpB;
//----------------------------------------------------------------------
};
//==============================================================================
#undef SQRT_2
//==============================================================================
} // namespace Wavechild670
//==============================================================================
#endif // __F670L_STEREO_PROCESSOR_HPP_9D267F6C__
//==============================================================================