Skip to content

Commit

Permalink
Update to Latest Airwin
Browse files Browse the repository at this point in the history
  • Loading branch information
baconpaul committed Feb 4, 2024
1 parent 57d1a85 commit 0907db8
Show file tree
Hide file tree
Showing 10 changed files with 3,375 additions and 194 deletions.
2 changes: 1 addition & 1 deletion libs/airwindows
Submodule airwindows updated 165 files
29 changes: 29 additions & 0 deletions res/awpdoc/CloudCoat.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# CloudCoat is an array of blur effects with a taste for evil.

Welcome back to the dark side of Airwindows!

CloudCoat starts as an experiment. What if there was ClearCoat (a bank of small reverbs) except all the delays were allpasses?

Okay, so a bit of explanation: allpasses are like reverb parts, but they make stuff sound smeary and blurred, like bloom reverbs. I've got a bloom reverb, MV, which is just a stack of allpasses. Most of my recent work is about avoiding allpasses completely by using reverb matrixes that give me LOTS of echo returns, impossible numbers, so I don't have to cheat with allpasses. This kind of works and kind of doesn't (work in progress, see my recent livestreams). But what would happen if you took what was clearly a reverb, and just replaced all the delays with allpasses?

That's ClearCoat and CloudCoat. The idea was I could give a completely different texture, but using literally all the same reverb constants, and then I could hear what it was like. I expected it to be more a cloudy, diffuse texture, hence 'cloudcoat'.

You might notice one difference right away: ClearCoat sounds a lot roomier. That's because it's designed with a little bit of feedback to fill it out. Sustain, if you will. It's also way more spacious, and way more metallic and ringy. This is in line with how it only uses delays, and is all part of the research.

CloudCoat with sustain all the way off, is quite different. Depth and spaciousness is almost gone, but there's no metallicness either. It's like essence of fake artificial reverb blur. Remember, this too is a 4x4 Householder matrix: it's a complicated pile of allpasses, not something primitive like MV. I think it might find uses on pads or ambient sounds, or could be used to feed into ClearCoat at the same 'select' setting to create a more powerful room sound. With sustain all the way off, you can do many polite and nice things with CloudCoat.

Then, throw it on some drums and turn the sustain up and ALL HELL BREAKS LOOSE :)

CloudCoat is applying a kind of nonlinear reverb, like your classic 'nonlin' gated verb settings, but Airwindowsized. I'm allowing feedback, but of the four 'channels' of Householder feedback, each is also modulated by the output of the one next to it (a totally different sound)… WITHOUT smoothing. So the feedback is broken up by four banks of allpass output and cranked up to the point of meltdown, and that's CloudCoat. It disrupts the signal wildly and fiercely.

Why?

Because I tried it, on a livestream, and the drums absolutely exploded like nothing I've ever heard. There's rasp and rattle and an effect much like extreme compression while in a stone drum room, but there's no compression and no stone room. It just makes that sound. Instead of making it out of compressed, flat-topped compression smash, it's making the madness happen INSIDE the sound, meaning you can make it brutal and unbearable with ClearCoat and THEN loudenate it, unlike any other sort of compression or distortion. CloudCoat adds a whole new type of trash that is dynamic with your sound (again, nonlin) and automatically dials itself back if the source energy level does. It's a huge, nasty, energy-laden meltdown that can be escalated to pretty much any degree… and then dialed back down again, to pretty much any level of controllability, so long as you're using it on noisy percussion and as long as you're okay with its signature trash-sound, which is not like anything else and which is independent of added compression and distortion.

And then you can do blur/texture effects with the sustain on 0. Just don't bother trying to make it work with tiny amounts of sustain: it basically can't. 0 or trash are your only options, and then there is a universe of trash and meltdown if trash you choose.

But seriously, why?

Because it makes me laugh with delight when snares go off like something out of the imagination of Trent Reznor. I don't know what to tell you. Enjoy CloudCoat, if it's the kind of thing you enjoy.


390 changes: 197 additions & 193 deletions src/ModuleAdd.h

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/autogen_airwin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ set(AIRWIN_SOURCES
src/autogen_airwin/ClipOnly2Proc.cpp
src/autogen_airwin/ClipSoftly.cpp
src/autogen_airwin/ClipSoftlyProc.cpp
src/autogen_airwin/CloudCoat.cpp
src/autogen_airwin/CloudCoatProc.cpp
src/autogen_airwin/Coils.cpp
src/autogen_airwin/CoilsProc.cpp
src/autogen_airwin/Coils2.cpp
Expand Down Expand Up @@ -747,6 +749,8 @@ set(AIRWIN_SOURCES
src/autogen_airwin/curveProc.cpp
src/autogen_airwin/kCathedral.cpp
src/autogen_airwin/kCathedralProc.cpp
src/autogen_airwin/kCathedral2.cpp
src/autogen_airwin/kCathedral2Proc.cpp
src/autogen_airwin/kChamberAR.cpp
src/autogen_airwin/kChamberARProc.cpp
src/autogen_airwin/kPlateA.cpp
Expand Down
238 changes: 238 additions & 0 deletions src/autogen_airwin/CloudCoat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/* ========================================
* CloudCoat - CloudCoat.h
* Copyright (c) airwindows, Airwindows uses the MIT license
* ======================================== */

#ifndef __CloudCoat_H
#include "CloudCoat.h"
#endif
namespace airwin2rack::CloudCoat {

AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new CloudCoat(audioMaster);}

CloudCoat::CloudCoat(audioMasterCallback audioMaster) :
AudioEffectX(audioMaster, kNumPrograms, kNumParameters)
{
A = 0.5;
B = 0.5;
C = 1.0;

for(int count = 0; count < kshortA+2; count++) {aAL[count] = 0.0; aAR[count] = 0.0;}
for(int count = 0; count < kshortB+2; count++) {aBL[count] = 0.0; aBR[count] = 0.0;}
for(int count = 0; count < kshortC+2; count++) {aCL[count] = 0.0; aCR[count] = 0.0;}
for(int count = 0; count < kshortD+2; count++) {aDL[count] = 0.0; aDR[count] = 0.0;}
for(int count = 0; count < kshortE+2; count++) {aEL[count] = 0.0; aER[count] = 0.0;}
for(int count = 0; count < kshortF+2; count++) {aFL[count] = 0.0; aFR[count] = 0.0;}
for(int count = 0; count < kshortG+2; count++) {aGL[count] = 0.0; aGR[count] = 0.0;}
for(int count = 0; count < kshortH+2; count++) {aHL[count] = 0.0; aHR[count] = 0.0;}
for(int count = 0; count < kshortI+2; count++) {aIL[count] = 0.0; aIR[count] = 0.0;}
for(int count = 0; count < kshortJ+2; count++) {aJL[count] = 0.0; aJR[count] = 0.0;}
for(int count = 0; count < kshortK+2; count++) {aKL[count] = 0.0; aKR[count] = 0.0;}
for(int count = 0; count < kshortL+2; count++) {aLL[count] = 0.0; aLR[count] = 0.0;}
for(int count = 0; count < kshortM+2; count++) {aML[count] = 0.0; aMR[count] = 0.0;}
for(int count = 0; count < kshortN+2; count++) {aNL[count] = 0.0; aNR[count] = 0.0;}
for(int count = 0; count < kshortO+2; count++) {aOL[count] = 0.0; aOR[count] = 0.0;}
for(int count = 0; count < kshortP+2; count++) {aPL[count] = 0.0; aPR[count] = 0.0;}

feedbackAL = 0.0;
feedbackBL = 0.0;
feedbackCL = 0.0;
feedbackDL = 0.0;

previousAL = 0.0;
previousBL = 0.0;
previousCL = 0.0;
previousDL = 0.0;
previousEL = 0.0;

feedbackDR = 0.0;
feedbackHR = 0.0;
feedbackLR = 0.0;
feedbackPR = 0.0;

avgAL = 0.0;
avgBL = 0.0;
avgCL = 0.0;
avgDL = 0.0;

avgDR = 0.0;
avgHR = 0.0;
avgLR = 0.0;
avgPR = 0.0;

previousAR = 0.0;
previousBR = 0.0;
previousCR = 0.0;
previousDR = 0.0;
previousER = 0.0;

prevMulchAL = 0.0;
prevMulchAR = 0.0;

tailL = 0.0;
tailR = 0.0;

for(int count = 0; count < 6; count++) {lastRefL[count] = 0.0; lastRefR[count] = 0.0;}

countAL = 1;
countBL = 1;
countCL = 1;
countDL = 1;
countEL = 1;
countFL = 1;
countGL = 1;
countHL = 1;
countIL = 1;
countJL = 1;
countKL = 1;
countLL = 1;
countML = 1;
countNL = 1;
countOL = 1;
countPL = 1;

countAR = 1;
countBR = 1;
countCR = 1;
countDR = 1;
countER = 1;
countFR = 1;
countGR = 1;
countHR = 1;
countIR = 1;
countJR = 1;
countKR = 1;
countLR = 1;
countMR = 1;
countNR = 1;
countOR = 1;
countPR = 1;

cycle = 0;

shortA = 336;
shortB = 1660;
shortC = 386;
shortD = 623;
shortE = 693;
shortF = 1079;
shortG = 891;
shortH = 1574;
shortI = 24;
shortJ = 2641;
shortK = 1239;
shortL = 775;
shortM = 11;
shortN = 3104;
shortO = 55;
shortP = 2366;
prevcloudcoat = -1;

fpdL = 1.0; while (fpdL < 16386) fpdL = rand()*UINT32_MAX;
fpdR = 1.0; while (fpdR < 16386) fpdR = rand()*UINT32_MAX;
//this is reset: values being initialized only once. Startup values, whatever they are.

_canDo.insert("plugAsChannelInsert"); // plug-in can be used as a channel insert effect.
_canDo.insert("plugAsSend"); // plug-in can be used as a send effect.
_canDo.insert("x2in2out");
setNumInputs(kNumInputs);
setNumOutputs(kNumOutputs);
setUniqueID(kUniqueId);
canProcessReplacing(); // supports output replacing
canDoubleReplacing(); // supports double precision processing
programsAreChunks(true);
vst_strncpy (_programName, "Default", kVstMaxProgNameLen); // default program name
}

CloudCoat::~CloudCoat() {}
VstInt32 CloudCoat::getVendorVersion () {return 1000;}
void CloudCoat::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);}
void CloudCoat::getProgramName(char *name) {vst_strncpy (name, _programName, kVstMaxProgNameLen);}
//airwindows likes to ignore this stuff. Make your own programs, and make a different plugin rather than
//trying to do versioning and preventing people from using older versions. Maybe they like the old one!

static float pinParameter(float data)
{
if (data < 0.0f) return 0.0f;
if (data > 1.0f) return 1.0f;
return data;
}

void CloudCoat::setParameter(VstInt32 index, float value) {
switch (index) {
case kParamA: A = value; break;
case kParamB: B = value; break;
case kParamC: C = value; break;
default: break; // unknown parameter, shouldn't happen!
}
}

float CloudCoat::getParameter(VstInt32 index) {
switch (index) {
case kParamA: return A; break;
case kParamB: return B; break;
case kParamC: return C; break;
default: break; // unknown parameter, shouldn't happen!
} return 0.0; //we only need to update the relevant name, this is simple to manage
}

void CloudCoat::getParameterName(VstInt32 index, char *text) {
switch (index) {
case kParamA: vst_strncpy (text, "Select", kVstMaxParamStrLen); break;
case kParamB: vst_strncpy (text, "Sustain", kVstMaxParamStrLen); break;
case kParamC: vst_strncpy (text, "Dry/Wet", kVstMaxParamStrLen); break;
default: break; // unknown parameter, shouldn't happen!
} //this is our labels for displaying in the VST host
}

void CloudCoat::getParameterDisplay(VstInt32 index, char *text) {
switch (index) {
case kParamA: int2string ((VstInt32)( A * 16.999 ), text, kVstMaxParamStrLen); break;
case kParamB: float2string (B, text, kVstMaxParamStrLen); break;
case kParamC: float2string (C, text, kVstMaxParamStrLen); break;
default: break; // unknown parameter, shouldn't happen!
} //this displays the values and handles 'popups' where it's discrete choices
}

void CloudCoat::getParameterLabel(VstInt32 index, char *text) {
switch (index) {
case kParamA: vst_strncpy (text, "", kVstMaxParamStrLen); break;
case kParamB: vst_strncpy (text, "", kVstMaxParamStrLen); break;
case kParamC: vst_strncpy (text, "", kVstMaxParamStrLen); break;
default: break; // unknown parameter, shouldn't happen!
}
}

VstInt32 CloudCoat::canDo(char *text)
{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know

bool CloudCoat::getEffectName(char* name) {
vst_strncpy(name, "CloudCoat", kVstMaxProductStrLen); return true;
}

VstPlugCategory CloudCoat::getPlugCategory() {return kPlugCategEffect;}

bool CloudCoat::getProductString(char* text) {
vst_strncpy (text, "airwindows CloudCoat", kVstMaxProductStrLen); return true;
}

bool CloudCoat::getVendorString(char* text) {
vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true;
}
bool CloudCoat::parameterTextToValue(VstInt32 index, const char *text, float &value) {
switch(index) {
case kParamB: { auto b = string2float(text, value); return b; break; }
case kParamC: { auto b = string2float(text, value); return b; break; }

}
return false;
}
bool CloudCoat::canConvertParameterTextToValue(VstInt32 index) {
switch(index) {
case kParamB: return true;
case kParamC: return true;

}
return false;
}
} // end namespace
Loading

0 comments on commit 0907db8

Please sign in to comment.