Skip to content

Commit dfd4299

Browse files
Merge pull request #34 from schollz/morechow
more Tape plugins
2 parents 48021ae + 59e46a5 commit dfd4299

20 files changed

+1276
-0
lines changed

CMakeLists.txt

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,80 @@ sc_add_server_plugin(
726726
"${AnalogVintageDistortion_schelp_files}"
727727
)
728728

729+
730+
731+
# AnalogLoss
732+
set(
733+
AnalogLoss_cpp_files
734+
plugins/ChowDSP/AnalogLoss.hpp
735+
plugins/ChowDSP/AnalogLoss.cpp
736+
)
737+
set(
738+
AnalogLoss_sc_files
739+
plugins/ChowDSP/AnalogLoss.sc
740+
)
741+
set(
742+
AnalogLoss_schelp_files
743+
plugins/ChowDSP/AnalogLoss.schelp
744+
)
745+
746+
sc_add_server_plugin(
747+
"${project_name}" # destination directory
748+
"AnalogLoss" # target name
749+
"${AnalogLoss_cpp_files}"
750+
"${AnalogLoss_sc_files}"
751+
"${AnalogLoss_schelp_files}"
752+
)
753+
754+
755+
756+
# AnalogDegrade
757+
set(
758+
AnalogDegrade_cpp_files
759+
plugins/ChowDSP/AnalogDegrade.hpp
760+
plugins/ChowDSP/AnalogDegrade.cpp
761+
)
762+
set(
763+
AnalogDegrade_sc_files
764+
plugins/ChowDSP/AnalogDegrade.sc
765+
)
766+
set(
767+
AnalogDegrade_schelp_files
768+
plugins/ChowDSP/AnalogDegrade.schelp
769+
)
770+
771+
sc_add_server_plugin(
772+
"${project_name}" # destination directory
773+
"AnalogDegrade" # target name
774+
"${AnalogDegrade_cpp_files}"
775+
"${AnalogDegrade_sc_files}"
776+
"${AnalogDegrade_schelp_files}"
777+
)
778+
779+
780+
# AnalogChew
781+
set(
782+
AnalogChew_cpp_files
783+
plugins/ChowDSP/AnalogChew.hpp
784+
plugins/ChowDSP/AnalogChew.cpp
785+
)
786+
set(
787+
AnalogChew_sc_files
788+
plugins/ChowDSP/AnalogChew.sc
789+
)
790+
set(
791+
AnalogChew_schelp_files
792+
plugins/ChowDSP/AnalogChew.schelp
793+
)
794+
795+
sc_add_server_plugin(
796+
"${project_name}" # destination directory
797+
"AnalogChew" # target name
798+
"${AnalogChew_cpp_files}"
799+
"${AnalogChew_sc_files}"
800+
"${AnalogChew_schelp_files}"
801+
)
802+
729803
# AnalogFoldOsc
730804
set(
731805
AnalogFoldOsc_cpp_files
@@ -962,3 +1036,4 @@ sc_add_server_plugin(
9621036
"${VA1Pole_sc_files}"
9631037
"${VA1Pole_schelp_files}"
9641038
)
1039+

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ See the `PortedPlugins.schelp` help file for an overview inside of SuperCollider
3131
- **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).
3232
- **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).
3333
- **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).
34+
- **AnalogChew** - Virtual analog tape model of tape chewing. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
35+
- **AnalogLoss** - Virtual analog tape model of loss emulation. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
36+
- **AnalogDegrade** - Virtual analog tape model of tape degradation. Ported from [Jatin Chowdhury's ChowDSP-VCV-rack project](https://github.com/jatinchowdhury18/ChowDSP-VCV).
3437
- **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.
3538
- **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).
3639
- **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).

plugins/ChowDSP/AnalogChew.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// AnalogChew.cpp
2+
// Mads Kjeldgaard (mail@madskjeldgaard.dk)
3+
4+
#include "AnalogChew.hpp"
5+
6+
#include "SC_PlugIn.hpp"
7+
8+
static InterfaceTable *ft;
9+
10+
namespace AnalogChew {
11+
12+
AnalogChew::AnalogChew() {
13+
samplerate = sampleRate();
14+
15+
filt.reset(samplerate, int(samplerate * 0.02f));
16+
dropout.prepare((double)samplerate);
17+
cookParams(samplerate, 0.5, 0.5, 0.5);
18+
19+
mCalcFunc = make_calc_function<AnalogChew, &AnalogChew::next>();
20+
next(1);
21+
}
22+
23+
AnalogChew::~AnalogChew() {}
24+
25+
float AnalogChew::uniform() { return ((float)rand() / (RAND_MAX)); }
26+
27+
void AnalogChew::cookParams(float fs, float depthParam, float freqParam,
28+
float varParam) {
29+
const float highFreq = std::min(22000.0f, 0.49f * fs);
30+
const float freqChange = highFreq - 5000.0f;
31+
32+
auto depth = depthParam;
33+
auto freq = freqParam;
34+
if (freq == 0.0f) {
35+
mix = 0.0f;
36+
filt.setFreq(highFreq);
37+
} else if (freq == 1.0f) {
38+
mix = 1.0f;
39+
power = 3.0f * depth;
40+
filt.setFreq(highFreq - freqChange * depth);
41+
} else if (sampleCounter >= samplesUntilChange) {
42+
sampleCounter = 0;
43+
isCrinkled = !isCrinkled;
44+
45+
if (isCrinkled) // start crinkle
46+
{
47+
mix = 1.0f;
48+
power = (1.0f + 2.0f * uniform()) * depth;
49+
filt.setFreq(highFreq - freqChange * depth);
50+
samplesUntilChange = getWetTime(freq, depth, varParam);
51+
} else // end crinkle
52+
{
53+
mix = 0.0f;
54+
filt.setFreq(highFreq);
55+
samplesUntilChange = getDryTime(freq, varParam);
56+
}
57+
} else {
58+
power = (1.0f + 2.0f * uniform()) * depth;
59+
if (isCrinkled) {
60+
filt.setFreq(highFreq - freqChange * depth);
61+
filt.setFreq(highFreq - freqChange * depth);
62+
}
63+
}
64+
65+
dropout.setMix(mix);
66+
dropout.setPower(1.0f + power);
67+
}
68+
69+
void AnalogChew::next(int nSamples) {
70+
float depth = in0(Depth);
71+
float freq = in0(Frequency);
72+
float var = in0(Variance);
73+
74+
cookParams(samplerate, depth, freq, var);
75+
76+
const float *input = in(Input);
77+
float *outbuf = out(Out1);
78+
79+
for (int i = 0; i < nSamples; ++i) {
80+
// get input
81+
float x = mkutils::constrain(input[i], -1.0f, 1.0f);
82+
x = dropout.processSample(x);
83+
x = filt.processSample(x);
84+
outbuf[i] = x;
85+
sampleCounter++;
86+
}
87+
}
88+
89+
void AnalogChew::clear(int nSamples) { ClearUnitOutputs(this, nSamples); }
90+
91+
} // namespace AnalogChew
92+
93+
PluginLoad(AnalogChewUGens) {
94+
// Plugin magic
95+
ft = inTable;
96+
registerUnit<AnalogChew::AnalogChew>(ft, "AnalogChew", false);
97+
}

plugins/ChowDSP/AnalogChew.hpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// AnalogChew.hpp
2+
// Mads Kjeldgaard (mail@madskjeldgaard.dk)
3+
4+
#pragma once
5+
6+
#include "SC_PlugIn.hpp"
7+
#include "../mkutils.hpp"
8+
#include "DegradeFilter.h"
9+
#include "Dropout.h"
10+
11+
namespace AnalogChew {
12+
13+
class AnalogChew : public SCUnit {
14+
public:
15+
AnalogChew();
16+
17+
// Destructor
18+
~AnalogChew();
19+
20+
inline int getDryTime(float freq, float var)
21+
{
22+
auto tScale = std::pow(freq, 0.1f);
23+
auto varScale = std::pow(((float) rand() / (RAND_MAX))* 2.0f, var);
24+
25+
auto minVal = (int) ((1.0f - tScale) * samplerate * varScale);
26+
auto maxVal = (int) ((2.0f - 1.99f * tScale) * samplerate * varScale);
27+
return (int) ((int) rand()) % (maxVal - minVal) + minVal;
28+
}
29+
30+
inline int getWetTime(float freq, float depth, float var)
31+
{
32+
auto tScale = std::pow(freq, 0.1f);
33+
auto start = 0.2f + 0.8f * depth;
34+
auto end = start - (0.001f + 0.01f * depth);
35+
auto varScale = std::pow(((float) rand() / (RAND_MAX))* 2.0f, var);
36+
37+
auto minVal = (int) ((1.0f - tScale) * samplerate * varScale);
38+
auto maxVal = (int) (((1.0f - tScale) + start - end * tScale) * samplerate * varScale);
39+
return (int) ((int) rand()) % (maxVal - minVal) + minVal;
40+
}
41+
private:
42+
// Calc function
43+
void next(int nSamples);
44+
void clear(int nSamples);
45+
float uniform();
46+
void cookParams(float fs, float depthParam, float freqParam, float varParam);
47+
48+
enum InputParams { Input, Depth, Frequency, Variance, NumInputParams };
49+
enum Outputs { Out1, NumOutputParams };
50+
51+
float samplerate = 44100.0f;
52+
float mix = 0.0f;
53+
float power = 0.0f;
54+
int samplesUntilChange = 1000;
55+
bool isCrinkled = false;
56+
int sampleCounter = 0;
57+
int nextCounter = 19;
58+
59+
Dropout dropout;
60+
DegradeFilter filt;
61+
62+
};
63+
64+
} // namespace AnalogChew

plugins/ChowDSP/AnalogChew.sc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
AnalogChew : UGen {
2+
*ar { |input, depth=0.5, freq=0.5, variance=0.5|
3+
^this.multiNew('audio', input, depth, freq, variance);
4+
}
5+
6+
checkInputs {
7+
/* TODO */
8+
^this.checkValidInputs;
9+
}
10+
}
11+

plugins/ChowDSP/AnalogChew.schelp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
CLASS:: AnalogChew
2+
SUMMARY:: Analog tape chew emulation
3+
RELATED::HelpSource/Overview/PortedPlugins
4+
CATEGORIES::UGens>VirtualAnalog
5+
6+
DESCRIPTION::
7+
8+
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::.
9+
This smaller version is mostly useful as a tape chew.
10+
11+
CLASSMETHODS::
12+
13+
METHOD::ar
14+
15+
ARGUMENT::input
16+
Audio input
17+
18+
ARGUMENT::depth
19+
Depth controls how deep the tape is chewed. 0.0 to 1.0.
20+
21+
ARGUMENT::frequency
22+
Frequency controls how much space there is between bits of tape that have been chewed up. Useful to toggle randomly between 0 and 1.
23+
24+
ARGUMENT::variance
25+
Variance determines how much randomness there is in determining the amount of space between chewed up sections. 0.0 to 1.0.
26+
27+
28+
EXAMPLES::
29+
30+
code::
31+
s.boot // Boot the server
32+
33+
b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
34+
35+
// move the mouse between the left and right to hear the differences
36+
// between no effect (left) and effected (right)
37+
(
38+
SynthDef(\chew, {| out = 0, bufnum = 0 |
39+
var snd=PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum),loop:1);
40+
var freq=LFTri.kr(1/3,Rand(0,2),0.5,0.5);
41+
var depth=LFTri.kr(1/4,Rand(0,2),0.5,0.5);
42+
var variance=LFTri.kr(1/5,Rand(0,2),0.5,0.5);
43+
snd=SelectX.ar(MouseX.kr(),[
44+
snd,
45+
AnalogChew.ar(snd,depth,freq,variance);
46+
]);
47+
Out.ar(out,snd!2);
48+
}).play(s, [\out, 0, \bufnum, b]);
49+
::
50+

0 commit comments

Comments
 (0)