-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
3,375 additions
and
194 deletions.
There are no files selected for viewing
Submodule airwindows
updated
165 files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
|
||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.