Skip to content

Commit 839bf8e

Browse files
committed
Update to Latest Airwin
1 parent 7f5a66c commit 839bf8e

19 files changed

Lines changed: 3309 additions & 338 deletions

libs/airwindows

Submodule airwindows updated 359 files

res/awpdoc/Suzan.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Suzan is a new type of ladder filter.
2+
3+
So a funny thing happened to me on the way to Dattorro…
4+
5+
I was talking about the very simple state variable filter I made, Dattorro, and how it was very handy, could even substitute for a biquad filter according to Andy from Cytomic who's an eager advocate of these (as opposed to, say, a biquad filter of direct form 1), and how I'd come up with a twist on it using only a sin() function to do the unexpected thing of subtracting the distorted bandpass element FROM the lowpass, and how that had a neat tone I liked. The twist was new, and I was excited about the possibilities.
6+
7+
Then, on a famously crotchety forum, a guy popped up to object… saying I shouldn't call it not a biquad. It's just an SVF and not direct form 1, but it's still a biquadratic filter. You could even have literal analog filters that are biquads. I had the language wrong and he apologized for the fact that this drove him up the wall.
8+
9+
He's Antoine Portes, and he's writing an experimental book about filters called Working Class Filter Design. Biquadratic means the transfer function's denominator is a quadratic formula, another name for second order polynomial. He's been trying to do a really good Moog ladder, which apparently is more like fourth order, and he notes that we use Q for resonance, but there's another part that goes 1/(2*Q) and this doesn't have a consistent name. He's calling it Damping, but suggests if you don't like that you can call it Suzan for all the difference it'll make to him.
10+
11+
Naturally, I was charmed though his math is over my foolish head :) and so, I got busy again, except it was with experimenting in code rather than figuring out the math of it. And I told him I'd name the filter, meant to be experiments on this fourth-order, Moog-flavored filter, 'Suzan' in his honor.
12+
13+
And this is the result. It's a small stack of SVFs. The difference is, Antoine understandably is interested in representing these things in correct math, and doing sensible things at least some of the time. Me on the other hand… my whole deal is being able to try things that don't exist yet. By all rights the AIs should be paying me to come up with novel things for them (maybe there'll come a day when that's a reality).
14+
15+
And so, Suzan is not two but three SVFs in series. And the SVFs are still normal, except I'm up to my Dattorro tricks but even worse. Stage A subtracts the bandpass of stage C. Stage B subtracts the bandpass of stage A… and stage C adds the bandpass of stage B. Oh, except they're all the sines of those bandpasses, and the first two are using half the amplitude of the bandpass, the final one which adds is using the full amplitude going into the sine function.
16+
17+
I don't claim justification for this or an analysis of why it works. Swept way up high it can have high frequency instability when hit with full blast white noise, which I hope doesn't cause issues (I got it to where it was simply a boost but didn't blow up). I find it's a nice chunky resonant peak and even gives appropriate amounts of bass restriction when resonance is turned up… and the inappropriate use of feedback across the stages does a nice job of giving a colorful texture. One I am intimately familiar with both from records, and from owning everything from a MG-1 Concertmate to a Werkstatt to a Sub Phatty. But we're not calling it that, because it isn't one of those. It's Suzan, and it's trying to bring the right kind of mojo to my filter collection. I hope you like it :)
18+
19+

src/ModuleAdd.h

Lines changed: 256 additions & 248 deletions
Large diffs are not rendered by default.

src/autogen_airwin/ADClip9.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/* ========================================
2+
* ADClip9 - ADClip9.h
3+
* Copyright (c) airwindows, Airwindows uses the MIT license
4+
* ======================================== */
5+
6+
#ifndef __ADClip9_H
7+
#include "ADClip9.h"
8+
#endif
9+
#include <cmath>
10+
#include <cstdlib>
11+
#include <algorithm>
12+
namespace airwinconsolidated::ADClip9 {
13+
14+
AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new ADClip9(audioMaster);}
15+
16+
ADClip9::ADClip9(audioMasterCallback audioMaster) :
17+
AudioEffectX(audioMaster, kNumPrograms, kNumParameters)
18+
{
19+
A = 0.0;
20+
B = 0.0;
21+
C = 0.7;
22+
D = 0.75;
23+
E = 0.0;
24+
25+
lastSampleL = 0.0;
26+
wasPosClipL = false;
27+
wasNegClipL = false;
28+
lastSampleR = 0.0;
29+
wasPosClipR = false;
30+
wasNegClipR = false;
31+
for (int x = 0; x < 17; x++) {intermediateL[x] = 0.0; intermediateR[x] = 0.0;}
32+
for (int x = 0; x < 33; x++) {slewL[x] = 0.0; slewR[x] = 0.0;}
33+
34+
fpdL = 1.0; while (fpdL < 16386) fpdL = rand()*UINT32_MAX;
35+
fpdR = 1.0; while (fpdR < 16386) fpdR = rand()*UINT32_MAX;
36+
//this is reset: values being initialized only once. Startup values, whatever they are.
37+
38+
_canDo.insert("plugAsChannelInsert"); // plug-in can be used as a channel insert effect.
39+
_canDo.insert("plugAsSend"); // plug-in can be used as a send effect.
40+
_canDo.insert("x2in2out");
41+
setNumInputs(kNumInputs);
42+
setNumOutputs(kNumOutputs);
43+
setUniqueID(kUniqueId);
44+
canProcessReplacing(); // supports output replacing
45+
canDoubleReplacing(); // supports double precision processing
46+
programsAreChunks(true);
47+
vst_strncpy (_programName, "Default", kVstMaxProgNameLen); // default program name
48+
}
49+
50+
ADClip9::~ADClip9() {}
51+
VstInt32 ADClip9::getVendorVersion () {return 1000;}
52+
void ADClip9::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);}
53+
void ADClip9::getProgramName(char *name) {vst_strncpy (name, _programName, kVstMaxProgNameLen);}
54+
//airwindows likes to ignore this stuff. Make your own programs, and make a different plugin rather than
55+
//trying to do versioning and preventing people from using older versions. Maybe they like the old one!
56+
57+
static float pinParameter(float data)
58+
{
59+
if (data < 0.0f) return 0.0f;
60+
if (data > 1.0f) return 1.0f;
61+
return data;
62+
}
63+
64+
void ADClip9::setParameter(VstInt32 index, float value) {
65+
switch (index) {
66+
case kParamA: A = value; break;
67+
case kParamB: B = value; break;
68+
case kParamC: C = value; break;
69+
case kParamD: D = value; break;
70+
case kParamE: E = value; break;
71+
default: break; // unknown parameter, shouldn't happen!
72+
}
73+
}
74+
75+
float ADClip9::getParameter(VstInt32 index) {
76+
switch (index) {
77+
case kParamA: return A; break;
78+
case kParamB: return B; break;
79+
case kParamC: return C; break;
80+
case kParamD: return D; break;
81+
case kParamE: return E; break;
82+
default: break; // unknown parameter, shouldn't happen!
83+
} return 0.0; //we only need to update the relevant name, this is simple to manage
84+
}
85+
86+
void ADClip9::getParameterName(VstInt32 index, char *text) {
87+
switch (index) {
88+
case kParamA: vst_strncpy (text, "Boost", kVstMaxParamStrLen); break;
89+
case kParamB: vst_strncpy (text, "Match", kVstMaxParamStrLen); break;
90+
case kParamC: vst_strncpy (text, "Noise", kVstMaxParamStrLen); break;
91+
case kParamD: vst_strncpy (text, "Ceiling", kVstMaxParamStrLen); break;
92+
case kParamE: vst_strncpy (text, "Mode", kVstMaxParamStrLen); break;
93+
default: break; // unknown parameter, shouldn't happen!
94+
} //this is our labels for displaying in the VST host
95+
}
96+
97+
void ADClip9::getParameterDisplay(VstInt32 index, char *text) {
98+
switch (index) {
99+
case kParamA: float2string (A*18.0, text, kVstMaxParamStrLen); break;
100+
case kParamB: float2string (B, text, kVstMaxParamStrLen); break;
101+
case kParamC: float2string (C, text, kVstMaxParamStrLen); break;
102+
case kParamD: float2string (D, text, kVstMaxParamStrLen); break;
103+
case kParamE: switch((VstInt32)( E * 2.999 )) {
104+
case 0: vst_strncpy (text, "Boost", kVstMaxParamStrLen); break;
105+
case 1: vst_strncpy (text, "Match", kVstMaxParamStrLen); break;
106+
case 2: vst_strncpy (text, "ClipOnly", kVstMaxParamStrLen); break;
107+
default: break; // unknown parameter, shouldn't happen!
108+
} break;
109+
default: break; // unknown parameter, shouldn't happen!
110+
} //this displays the values and handles 'popups' where it's discrete choices
111+
}
112+
113+
void ADClip9::getParameterLabel(VstInt32 index, char *text) {
114+
switch (index) {
115+
case kParamA: vst_strncpy (text, "dB", kVstMaxParamStrLen); break;
116+
case kParamB: vst_strncpy (text, "dB", kVstMaxParamStrLen); break;
117+
case kParamC: vst_strncpy (text, "", kVstMaxParamStrLen); break;
118+
case kParamD: vst_strncpy (text, "", kVstMaxParamStrLen); break;
119+
case kParamE: vst_strncpy (text, "", kVstMaxParamStrLen); break;
120+
default: break; // unknown parameter, shouldn't happen!
121+
}
122+
}
123+
124+
VstInt32 ADClip9::canDo(char *text)
125+
{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know
126+
127+
bool ADClip9::getEffectName(char* name) {
128+
vst_strncpy(name, "ADClip9", kVstMaxProductStrLen); return true;
129+
}
130+
131+
VstPlugCategory ADClip9::getPlugCategory() {return kPlugCategEffect;}
132+
133+
bool ADClip9::getProductString(char* text) {
134+
vst_strncpy (text, "airwindows ADClip9", kVstMaxProductStrLen); return true;
135+
}
136+
137+
bool ADClip9::getVendorString(char* text) {
138+
vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true;
139+
}
140+
bool ADClip9::parameterTextToValue(VstInt32 index, const char *text, float &value) {
141+
switch(index) {
142+
case kParamA: { auto b = string2float(text, value); if (b) { value = value / (18.0); } return b; break; }
143+
case kParamB: { auto b = string2float(text, value); return b; break; }
144+
case kParamC: { auto b = string2float(text, value); return b; break; }
145+
case kParamD: { auto b = string2float(text, value); return b; break; }
146+
147+
}
148+
return false;
149+
}
150+
bool ADClip9::canConvertParameterTextToValue(VstInt32 index) {
151+
switch(index) {
152+
case kParamA: return true;
153+
case kParamB: return true;
154+
case kParamC: return true;
155+
case kParamD: return true;
156+
157+
}
158+
return false;
159+
}
160+
} // end namespace

src/autogen_airwin/ADClip9.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* ========================================
2+
* ADClip9 - ADClip9.h
3+
* Created 8/12/11 by SPIAdmin
4+
* Copyright (c) Airwindows, Airwindows uses the MIT license
5+
* ======================================== */
6+
7+
#ifndef __ADClip9_ADClip9_H
8+
#define __ADClip9_ADClip9_H
9+
10+
#ifndef __audioeffect__
11+
#include "../airwin_consolidated_base.h"
12+
#endif
13+
14+
#include <set>
15+
#include <string>
16+
#include <math.h>
17+
18+
namespace airwinconsolidated::ADClip9 {
19+
enum {
20+
kParamA =0,
21+
kParamB =1,
22+
kParamC =2,
23+
kParamD =3,
24+
kParamE =4,
25+
kNumParameters = 5
26+
}; //
27+
28+
const int kNumPrograms = 0;
29+
const int kNumInputs = 2;
30+
const int kNumOutputs = 2;
31+
const unsigned long kUniqueId = 'adct'; //Change this to what the AU identity is!
32+
33+
class ADClip9 :
34+
public AudioEffectX
35+
{
36+
public:
37+
ADClip9(audioMasterCallback audioMaster);
38+
~ADClip9();
39+
virtual bool getEffectName(char* name); // The plug-in name
40+
virtual VstPlugCategory getPlugCategory(); // The general category for the plug-in
41+
virtual bool getProductString(char* text); // This is a unique plug-in string provided by Steinberg
42+
virtual bool getVendorString(char* text); // Vendor info
43+
virtual VstInt32 getVendorVersion(); // Version number
44+
virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames);
45+
virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames);
46+
virtual void getProgramName(char *name); // read the name from the host
47+
virtual void setProgramName(char *name); // changes the name of the preset displayed in the host
48+
virtual float getParameter(VstInt32 index); // get the parameter value at the specified index
49+
virtual void setParameter(VstInt32 index, float value); // set the parameter at index to value
50+
virtual void getParameterLabel(VstInt32 index, char *text); // label for the parameter (eg dB)
51+
virtual void getParameterName(VstInt32 index, char *text); // name of the parameter
52+
virtual void getParameterDisplay(VstInt32 index, char *text); // text description of the current value
53+
// Added by the perl as inverses
54+
virtual bool parameterTextToValue(VstInt32 index, const char *text, float &value);
55+
virtual bool canConvertParameterTextToValue(VstInt32 index);
56+
virtual VstInt32 canDo(char *text);
57+
private:
58+
char _programName[kVstMaxProgNameLen + 1];
59+
std::set< std::string > _canDo;
60+
61+
float A;
62+
float B;
63+
float C;
64+
float D;
65+
float E;
66+
67+
double lastSampleL;
68+
double lastDryL;
69+
double intermediateL[18];
70+
double slewL[34];
71+
bool wasPosClipL;
72+
bool wasNegClipL;
73+
74+
double lastSampleR;
75+
double lastDryR;
76+
double intermediateR[18];
77+
double slewR[34];
78+
bool wasPosClipR;
79+
bool wasNegClipR;
80+
81+
uint32_t fpdL;
82+
uint32_t fpdR;
83+
//default stuff
84+
};
85+
86+
#endif
87+
} // end namespace

0 commit comments

Comments
 (0)