-
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
7 changed files
with
790 additions
and
366 deletions.
There are no files selected for viewing
Submodule airwindows
updated
84 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,20 @@ | ||
# DubSub2 is the essence of the Airwindows head bump. | ||
|
||
The final element for reinventing ToTape is in place, with DubSub2! | ||
|
||
I've always used this one particular algorithm, both for ToTape and for various bass-emphasis plugins. It acts like a combination between an IIR filter and a saturation. And it's got fantastic sound, but with a catch: it has to be controlled in the higher frequencies or it'll sound growly and distorted if you push it, and it's unstable. | ||
|
||
That's literal. I have to do stuff to control it or it will throw bass so hard that it sits around pushing DC. The algorithm has to be filtered because it's unstable, it'll constantly bring up deep bass no matter what. The sound of it is intrinsically tied to this behavior. | ||
|
||
So, what if I tried the technique I use in Parametric, and set up some biquad filters as bandpasses, and then stack them (slightly staggered, for tone purposes) to get better rejection of unwanted DC energy? What could go wrong? Well… it's tricky. If you do that, phase shifts will cause there to be a cancellation around the bandpass frequency. You'll get notches, the placement depending on what your filter bandwidth is. | ||
|
||
But hang on. Jack Endino's got a webpage where he's measured lots of real analog tape machines, showing the head bumps. And the thing is, on his measurements there's consistently a notch there, too. It's exactly an octave above the head bump, and that's part of the sound. | ||
|
||
So what's the bandpass resonance, when you're using two of them stacked, and then you want the notch produced by the phase shifting (already an unusual choice) to line up exactly an octave over the head bump resonance, so that your DubSub2 head bump will consistently behave like the real thing? You can set the head bump frequency to whatever you like (Jack finds that doubling the track width halves the head bump frequency, and of course going from 15 ips to 30 ips doubles the head bump frequency, and the notch stays exactly an octave higher). But the Q is what positions that notch. Since there is clearly no correct value for such a bizarre experiment, since super-shallow Q won't work, since using Butterworth (0.7071) is slightly too tight… what's the resonance number for the two stacked bandpasses? | ||
|
||
The golden ratio. | ||
|
||
…hope you enjoy DubSub2, and this is what will become the head bump for ToTape7 :) | ||
|
||
|
||
|
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,136 @@ | ||
/* ======================================== | ||
* DubSub2 - DubSub2.h | ||
* Copyright (c) airwindows, Airwindows uses the MIT license | ||
* ======================================== */ | ||
|
||
#ifndef __DubSub2_H | ||
#include "DubSub2.h" | ||
#endif | ||
#include <cmath> | ||
#include <algorithm> | ||
namespace airwinconsolidated::DubSub2 { | ||
|
||
AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new DubSub2(audioMaster);} | ||
|
||
DubSub2::DubSub2(audioMasterCallback audioMaster) : | ||
AudioEffectX(audioMaster, kNumPrograms, kNumParameters) | ||
{ | ||
A = 0.5; | ||
B = 0.5; | ||
C = 0.5; | ||
|
||
headBumpL = 0.0; | ||
headBumpR = 0.0; | ||
for (int x = 0; x < hdb_total; x++) {hdbA[x] = 0.0;hdbB[x] = 0.0;} | ||
//from ZBandpass, so I can use enums with it | ||
|
||
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 | ||
} | ||
|
||
DubSub2::~DubSub2() {} | ||
VstInt32 DubSub2::getVendorVersion () {return 1000;} | ||
void DubSub2::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);} | ||
void DubSub2::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 DubSub2::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 DubSub2::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 DubSub2::getParameterName(VstInt32 index, char *text) { | ||
switch (index) { | ||
case kParamA: vst_strncpy (text, "HeadBmp", kVstMaxParamStrLen); break; | ||
case kParamB: vst_strncpy (text, "HeadFrq", 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 DubSub2::getParameterDisplay(VstInt32 index, char *text) { | ||
switch (index) { | ||
case kParamA: float2string (A, text, kVstMaxParamStrLen); break; | ||
case kParamB: float2string (((B*B)*175.0)+25.0, 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 DubSub2::getParameterLabel(VstInt32 index, char *text) { | ||
switch (index) { | ||
case kParamA: vst_strncpy (text, "", kVstMaxParamStrLen); break; | ||
case kParamB: vst_strncpy (text, "hz", kVstMaxParamStrLen); break; | ||
case kParamC: vst_strncpy (text, "", kVstMaxParamStrLen); break; | ||
default: break; // unknown parameter, shouldn't happen! | ||
} | ||
} | ||
|
||
VstInt32 DubSub2::canDo(char *text) | ||
{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know | ||
|
||
bool DubSub2::getEffectName(char* name) { | ||
vst_strncpy(name, "DubSub2", kVstMaxProductStrLen); return true; | ||
} | ||
|
||
VstPlugCategory DubSub2::getPlugCategory() {return kPlugCategEffect;} | ||
|
||
bool DubSub2::getProductString(char* text) { | ||
vst_strncpy (text, "airwindows DubSub2", kVstMaxProductStrLen); return true; | ||
} | ||
|
||
bool DubSub2::getVendorString(char* text) { | ||
vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true; | ||
} | ||
bool DubSub2::parameterTextToValue(VstInt32 index, const char *text, float &value) { | ||
switch(index) { | ||
case kParamA: { auto b = string2float(text, value); return b; break; } | ||
case kParamB: { auto b = string2float(text, value); if (b) { value = sqrt(std::max((value - 25.0) / (175.0), 0.)); } return b; break; } | ||
case kParamC: { auto b = string2float(text, value); return b; break; } | ||
|
||
} | ||
return false; | ||
} | ||
bool DubSub2::canConvertParameterTextToValue(VstInt32 index) { | ||
switch(index) { | ||
case kParamA: return true; | ||
case kParamB: return true; | ||
case kParamC: return true; | ||
|
||
} | ||
return false; | ||
} | ||
} // end namespace |
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,88 @@ | ||
/* ======================================== | ||
* DubSub2 - DubSub2.h | ||
* Created 8/12/11 by SPIAdmin | ||
* Copyright (c) Airwindows, Airwindows uses the MIT license | ||
* ======================================== */ | ||
|
||
#ifndef __DubSub2_DubSub2_H | ||
#define __DubSub2_DubSub2_H | ||
|
||
#ifndef __audioeffect__ | ||
#include "../airwin_consolidated_base.h" | ||
#endif | ||
|
||
#include <set> | ||
#include <string> | ||
#include <math.h> | ||
|
||
namespace airwinconsolidated::DubSub2 { | ||
enum { | ||
kParamA =0, | ||
kParamB =1, | ||
kParamC =2, | ||
kNumParameters = 3 | ||
}; // | ||
|
||
const int kNumPrograms = 0; | ||
const int kNumInputs = 2; | ||
const int kNumOutputs = 2; | ||
const unsigned long kUniqueId = 'dbsc'; //Change this to what the AU identity is! | ||
|
||
class DubSub2 : | ||
public AudioEffectX | ||
{ | ||
public: | ||
DubSub2(audioMasterCallback audioMaster); | ||
~DubSub2(); | ||
virtual bool getEffectName(char* name); // The plug-in name | ||
virtual VstPlugCategory getPlugCategory(); // The general category for the plug-in | ||
virtual bool getProductString(char* text); // This is a unique plug-in string provided by Steinberg | ||
virtual bool getVendorString(char* text); // Vendor info | ||
virtual VstInt32 getVendorVersion(); // Version number | ||
virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames); | ||
virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames); | ||
virtual void getProgramName(char *name); // read the name from the host | ||
virtual void setProgramName(char *name); // changes the name of the preset displayed in the host | ||
virtual float getParameter(VstInt32 index); // get the parameter value at the specified index | ||
virtual void setParameter(VstInt32 index, float value); // set the parameter at index to value | ||
virtual void getParameterLabel(VstInt32 index, char *text); // label for the parameter (eg dB) | ||
virtual void getParameterName(VstInt32 index, char *text); // name of the parameter | ||
virtual void getParameterDisplay(VstInt32 index, char *text); // text description of the current value | ||
// Added by the perl as inverses | ||
virtual bool parameterTextToValue(VstInt32 index, const char *text, float &value); | ||
virtual bool canConvertParameterTextToValue(VstInt32 index); | ||
virtual VstInt32 canDo(char *text); | ||
private: | ||
char _programName[kVstMaxProgNameLen + 1]; | ||
std::set< std::string > _canDo; | ||
|
||
float A; | ||
float B; | ||
float C; | ||
|
||
double headBumpL; | ||
double headBumpR; | ||
enum { | ||
hdb_freq, | ||
hdb_reso, | ||
hdb_a0, | ||
hdb_a1, | ||
hdb_a2, | ||
hdb_b1, | ||
hdb_b2, | ||
hdb_sL1, | ||
hdb_sL2, | ||
hdb_sR1, | ||
hdb_sR2, | ||
hdb_total | ||
}; //fixed frequency biquad filter for ultrasonics, stereo | ||
double hdbA[hdb_total]; | ||
double hdbB[hdb_total]; | ||
|
||
uint32_t fpdL; | ||
uint32_t fpdR; | ||
//default stuff | ||
}; | ||
|
||
#endif | ||
} // end namespace |
Oops, something went wrong.