Skip to content

Commit

Permalink
Merge pull request #34 from schollz/morechow
Browse files Browse the repository at this point in the history
more Tape plugins
  • Loading branch information
madskjeldgaard authored Feb 16, 2023
2 parents 48021ae + 59e46a5 commit dfd4299
Show file tree
Hide file tree
Showing 20 changed files with 1,276 additions and 0 deletions.
75 changes: 75 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,80 @@ sc_add_server_plugin(
"${AnalogVintageDistortion_schelp_files}"
)



# AnalogLoss
set(
AnalogLoss_cpp_files
plugins/ChowDSP/AnalogLoss.hpp
plugins/ChowDSP/AnalogLoss.cpp
)
set(
AnalogLoss_sc_files
plugins/ChowDSP/AnalogLoss.sc
)
set(
AnalogLoss_schelp_files
plugins/ChowDSP/AnalogLoss.schelp
)

sc_add_server_plugin(
"${project_name}" # destination directory
"AnalogLoss" # target name
"${AnalogLoss_cpp_files}"
"${AnalogLoss_sc_files}"
"${AnalogLoss_schelp_files}"
)



# AnalogDegrade
set(
AnalogDegrade_cpp_files
plugins/ChowDSP/AnalogDegrade.hpp
plugins/ChowDSP/AnalogDegrade.cpp
)
set(
AnalogDegrade_sc_files
plugins/ChowDSP/AnalogDegrade.sc
)
set(
AnalogDegrade_schelp_files
plugins/ChowDSP/AnalogDegrade.schelp
)

sc_add_server_plugin(
"${project_name}" # destination directory
"AnalogDegrade" # target name
"${AnalogDegrade_cpp_files}"
"${AnalogDegrade_sc_files}"
"${AnalogDegrade_schelp_files}"
)


# AnalogChew
set(
AnalogChew_cpp_files
plugins/ChowDSP/AnalogChew.hpp
plugins/ChowDSP/AnalogChew.cpp
)
set(
AnalogChew_sc_files
plugins/ChowDSP/AnalogChew.sc
)
set(
AnalogChew_schelp_files
plugins/ChowDSP/AnalogChew.schelp
)

sc_add_server_plugin(
"${project_name}" # destination directory
"AnalogChew" # target name
"${AnalogChew_cpp_files}"
"${AnalogChew_sc_files}"
"${AnalogChew_schelp_files}"
)

# AnalogFoldOsc
set(
AnalogFoldOsc_cpp_files
Expand Down Expand Up @@ -962,3 +1036,4 @@ sc_add_server_plugin(
"${VA1Pole_sc_files}"
"${VA1Pole_schelp_files}"
)

3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ See the `PortedPlugins.schelp` help file for an overview inside of SuperCollider
- **AnalogSnareDrum** - Virtual analog 808 snare drum model. Original code by [Èmilie Gillet / Mutable Instruments](https://github.com/pichenettes/eurorack). Revisited by Ben Sergentanis for the [DaisySP DSP library](https://github.com/electro-smith/DaisySP).
- **AnalogTape** - Virtual analog tape model with variable oversampling and anti aliasing. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
- **AnalogVintageDistortion** - A virtual analog vintage EQ and distortion by Jatin Chowdhury. Features oversampling. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
- **AnalogChew** - Virtual analog tape model of tape chewing. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
- **AnalogLoss** - Virtual analog tape model of loss emulation. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
- **AnalogDegrade** - Virtual analog tape model of tape degradation. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
- **AnalogFoldOsc** - Buchla type of Oscillator with built in wavefolder circuit. Based on research by Fabián Esqueda, Henri Pöntynen, Vesa Välimäki and Julian D. Parker.
- **BLOsc** - Band limited oscillator. Original Author(s): Paul Batchelor, saw2 Faust by Julius Smith. Revisited by Ben Sergentanis for the [DaisySP DSP library](https://github.com/electro-smith/DaisySP).
- **Chen** - Chen's chaotic double scroll attractor, based on code from [Bryan Head's alternative Mutable Instruments firmware](https://github.com/qiemem/eurorack/releases/tag/v1.1.0).
Expand Down
97 changes: 97 additions & 0 deletions plugins/ChowDSP/AnalogChew.cpp
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);
}
64 changes: 64 additions & 0 deletions plugins/ChowDSP/AnalogChew.hpp
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
11 changes: 11 additions & 0 deletions plugins/ChowDSP/AnalogChew.sc
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;
}
}

50 changes: 50 additions & 0 deletions plugins/ChowDSP/AnalogChew.schelp
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]);
::

Loading

0 comments on commit dfd4299

Please sign in to comment.