-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from schollz/morechow
more Tape plugins
- Loading branch information
Showing
20 changed files
with
1,276 additions
and
0 deletions.
There are no files selected for viewing
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
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,97 @@ | ||
// AnalogChew.cpp | ||
// Mads Kjeldgaard ([email protected]) | ||
|
||
#include "AnalogChew.hpp" | ||
|
||
#include "SC_PlugIn.hpp" | ||
|
||
static InterfaceTable *ft; | ||
|
||
namespace AnalogChew { | ||
|
||
AnalogChew::AnalogChew() { | ||
samplerate = sampleRate(); | ||
|
||
filt.reset(samplerate, int(samplerate * 0.02f)); | ||
dropout.prepare((double)samplerate); | ||
cookParams(samplerate, 0.5, 0.5, 0.5); | ||
|
||
mCalcFunc = make_calc_function<AnalogChew, &AnalogChew::next>(); | ||
next(1); | ||
} | ||
|
||
AnalogChew::~AnalogChew() {} | ||
|
||
float AnalogChew::uniform() { return ((float)rand() / (RAND_MAX)); } | ||
|
||
void AnalogChew::cookParams(float fs, float depthParam, float freqParam, | ||
float varParam) { | ||
const float highFreq = std::min(22000.0f, 0.49f * fs); | ||
const float freqChange = highFreq - 5000.0f; | ||
|
||
auto depth = depthParam; | ||
auto freq = freqParam; | ||
if (freq == 0.0f) { | ||
mix = 0.0f; | ||
filt.setFreq(highFreq); | ||
} else if (freq == 1.0f) { | ||
mix = 1.0f; | ||
power = 3.0f * depth; | ||
filt.setFreq(highFreq - freqChange * depth); | ||
} else if (sampleCounter >= samplesUntilChange) { | ||
sampleCounter = 0; | ||
isCrinkled = !isCrinkled; | ||
|
||
if (isCrinkled) // start crinkle | ||
{ | ||
mix = 1.0f; | ||
power = (1.0f + 2.0f * uniform()) * depth; | ||
filt.setFreq(highFreq - freqChange * depth); | ||
samplesUntilChange = getWetTime(freq, depth, varParam); | ||
} else // end crinkle | ||
{ | ||
mix = 0.0f; | ||
filt.setFreq(highFreq); | ||
samplesUntilChange = getDryTime(freq, varParam); | ||
} | ||
} else { | ||
power = (1.0f + 2.0f * uniform()) * depth; | ||
if (isCrinkled) { | ||
filt.setFreq(highFreq - freqChange * depth); | ||
filt.setFreq(highFreq - freqChange * depth); | ||
} | ||
} | ||
|
||
dropout.setMix(mix); | ||
dropout.setPower(1.0f + power); | ||
} | ||
|
||
void AnalogChew::next(int nSamples) { | ||
float depth = in0(Depth); | ||
float freq = in0(Frequency); | ||
float var = in0(Variance); | ||
|
||
cookParams(samplerate, depth, freq, var); | ||
|
||
const float *input = in(Input); | ||
float *outbuf = out(Out1); | ||
|
||
for (int i = 0; i < nSamples; ++i) { | ||
// get input | ||
float x = mkutils::constrain(input[i], -1.0f, 1.0f); | ||
x = dropout.processSample(x); | ||
x = filt.processSample(x); | ||
outbuf[i] = x; | ||
sampleCounter++; | ||
} | ||
} | ||
|
||
void AnalogChew::clear(int nSamples) { ClearUnitOutputs(this, nSamples); } | ||
|
||
} // namespace AnalogChew | ||
|
||
PluginLoad(AnalogChewUGens) { | ||
// Plugin magic | ||
ft = inTable; | ||
registerUnit<AnalogChew::AnalogChew>(ft, "AnalogChew", false); | ||
} |
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,64 @@ | ||
// AnalogChew.hpp | ||
// Mads Kjeldgaard ([email protected]) | ||
|
||
#pragma once | ||
|
||
#include "SC_PlugIn.hpp" | ||
#include "../mkutils.hpp" | ||
#include "DegradeFilter.h" | ||
#include "Dropout.h" | ||
|
||
namespace AnalogChew { | ||
|
||
class AnalogChew : public SCUnit { | ||
public: | ||
AnalogChew(); | ||
|
||
// Destructor | ||
~AnalogChew(); | ||
|
||
inline int getDryTime(float freq, float var) | ||
{ | ||
auto tScale = std::pow(freq, 0.1f); | ||
auto varScale = std::pow(((float) rand() / (RAND_MAX))* 2.0f, var); | ||
|
||
auto minVal = (int) ((1.0f - tScale) * samplerate * varScale); | ||
auto maxVal = (int) ((2.0f - 1.99f * tScale) * samplerate * varScale); | ||
return (int) ((int) rand()) % (maxVal - minVal) + minVal; | ||
} | ||
|
||
inline int getWetTime(float freq, float depth, float var) | ||
{ | ||
auto tScale = std::pow(freq, 0.1f); | ||
auto start = 0.2f + 0.8f * depth; | ||
auto end = start - (0.001f + 0.01f * depth); | ||
auto varScale = std::pow(((float) rand() / (RAND_MAX))* 2.0f, var); | ||
|
||
auto minVal = (int) ((1.0f - tScale) * samplerate * varScale); | ||
auto maxVal = (int) (((1.0f - tScale) + start - end * tScale) * samplerate * varScale); | ||
return (int) ((int) rand()) % (maxVal - minVal) + minVal; | ||
} | ||
private: | ||
// Calc function | ||
void next(int nSamples); | ||
void clear(int nSamples); | ||
float uniform(); | ||
void cookParams(float fs, float depthParam, float freqParam, float varParam); | ||
|
||
enum InputParams { Input, Depth, Frequency, Variance, NumInputParams }; | ||
enum Outputs { Out1, NumOutputParams }; | ||
|
||
float samplerate = 44100.0f; | ||
float mix = 0.0f; | ||
float power = 0.0f; | ||
int samplesUntilChange = 1000; | ||
bool isCrinkled = false; | ||
int sampleCounter = 0; | ||
int nextCounter = 19; | ||
|
||
Dropout dropout; | ||
DegradeFilter filt; | ||
|
||
}; | ||
|
||
} // namespace AnalogChew |
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,11 @@ | ||
AnalogChew : UGen { | ||
*ar { |input, depth=0.5, freq=0.5, variance=0.5| | ||
^this.multiNew('audio', input, depth, freq, variance); | ||
} | ||
|
||
checkInputs { | ||
/* TODO */ | ||
^this.checkValidInputs; | ||
} | ||
} | ||
|
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,50 @@ | ||
CLASS:: AnalogChew | ||
SUMMARY:: Analog tape chew emulation | ||
RELATED::HelpSource/Overview/PortedPlugins | ||
CATEGORIES::UGens>VirtualAnalog | ||
|
||
DESCRIPTION:: | ||
|
||
This plugin is an analog tape chew emulation algorithm by Jatin Chowdhury, a mini version of the mindblowing link::https://github.com/jatinchowdhury18/AnalogTapeModel vst plugin::. For a deep dive, link::https://ccrma.stanford.edu/~jatin/420/tape/TapeModel_DAFx.pdf##see Chowdhury's paper on analog tape modelling::. | ||
This smaller version is mostly useful as a tape chew. | ||
|
||
CLASSMETHODS:: | ||
|
||
METHOD::ar | ||
|
||
ARGUMENT::input | ||
Audio input | ||
|
||
ARGUMENT::depth | ||
Depth controls how deep the tape is chewed. 0.0 to 1.0. | ||
|
||
ARGUMENT::frequency | ||
Frequency controls how much space there is between bits of tape that have been chewed up. Useful to toggle randomly between 0 and 1. | ||
|
||
ARGUMENT::variance | ||
Variance determines how much randomness there is in determining the amount of space between chewed up sections. 0.0 to 1.0. | ||
|
||
|
||
EXAMPLES:: | ||
|
||
code:: | ||
s.boot // Boot the server | ||
|
||
b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav"); | ||
|
||
// move the mouse between the left and right to hear the differences | ||
// between no effect (left) and effected (right) | ||
( | ||
SynthDef(\chew, {| out = 0, bufnum = 0 | | ||
var snd=PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum),loop:1); | ||
var freq=LFTri.kr(1/3,Rand(0,2),0.5,0.5); | ||
var depth=LFTri.kr(1/4,Rand(0,2),0.5,0.5); | ||
var variance=LFTri.kr(1/5,Rand(0,2),0.5,0.5); | ||
snd=SelectX.ar(MouseX.kr(),[ | ||
snd, | ||
AnalogChew.ar(snd,depth,freq,variance); | ||
]); | ||
Out.ar(out,snd!2); | ||
}).play(s, [\out, 0, \bufnum, b]); | ||
:: | ||
|
Oops, something went wrong.