AnalogTapeModel

Physical modelling signal processing for analog tape recording
Log | Files | Refs | Submodules | README | LICENSE

commit ba9b6c50a833149e21f0f1f838db455f5513faf5
parent 252953fde9d6eef498b7f9728477eff13055b089
Author: jatinchowdhury18 <jatinchowdhury18@users.noreply.github.com>
Date:   Sat, 18 Apr 2020 20:58:15 -0700

Add chew processing

Diffstat:
MPlugin/CHOWTapeModel.jucer | 6++++++
MPlugin/Source/PluginProcessor.cpp | 4++++
MPlugin/Source/PluginProcessor.h | 2++
APlugin/Source/Processors/Chew/ChewProcessor.cpp | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
APlugin/Source/Processors/Chew/ChewProcessor.h | 45+++++++++++++++++++++++++++++++++++++++++++++
APlugin/Source/Processors/Chew/Dropout.h | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MPlugin/Source/gui.xml | 0
7 files changed, 188 insertions(+), 0 deletions(-)

diff --git a/Plugin/CHOWTapeModel.jucer b/Plugin/CHOWTapeModel.jucer @@ -8,6 +8,12 @@ <GROUP id="{0178B10A-4A61-796A-5AB2-915D32AF6EEE}" name="Source"> <FILE id="Xn3V5v" name="gui.xml" compile="0" resource="1" file="Source/gui.xml"/> <GROUP id="{43BBFC88-4D0A-01B8-2635-3748470B94F4}" name="Processors"> + <GROUP id="{2F544AA2-63D9-E54A-A753-2E6249E85E60}" name="Chew"> + <FILE id="S5eP4b" name="ChewProcessor.cpp" compile="1" resource="0" + file="Source/Processors/Chew/ChewProcessor.cpp"/> + <FILE id="shEGgj" name="ChewProcessor.h" compile="0" resource="0" file="Source/Processors/Chew/ChewProcessor.h"/> + <FILE id="gw6Axu" name="Dropout.h" compile="0" resource="0" file="Source/Processors/Chew/Dropout.h"/> + </GROUP> <GROUP id="{344B63D7-2DBC-F9D2-ACD7-1B0671D4D024}" name="Degrade"> <FILE id="ac7jRp" name="DegradeFilter.h" compile="0" resource="0" file="Source/Processors/Degrade/DegradeFilter.h"/> <FILE id="qWC1GC" name="DegradeNoise.h" compile="0" resource="0" file="Source/Processors/Degrade/DegradeNoise.h"/> diff --git a/Plugin/Source/PluginProcessor.cpp b/Plugin/Source/PluginProcessor.cpp @@ -25,6 +25,7 @@ ChowtapeModelAudioProcessor::ChowtapeModelAudioProcessor() vts (*this, nullptr, Identifier ("Parameters"), createParameterLayout()), hysteresis (vts), degrade (vts), + chewer (vts), flutter (vts) { for (int ch = 0; ch < 2; ++ch) @@ -48,6 +49,7 @@ AudioProcessorValueTreeState::ParameterLayout ChowtapeModelAudioProcessor::creat LossFilter::createParameterLayout (params); Flutter::createParameterLayout (params); DegradeProcessor::createParameterLayout (params); + ChewProcessor::createParameterLayout (params); return { params.begin(), params.end() }; } @@ -120,6 +122,7 @@ void ChowtapeModelAudioProcessor::prepareToPlay (double sampleRate, int samplesP inGain.prepareToPlay (sampleRate, samplesPerBlock); hysteresis.prepareToPlay (sampleRate, samplesPerBlock); degrade.prepareToPlay (sampleRate, samplesPerBlock); + chewer.prepare (sampleRate, samplesPerBlock); for (int ch = 0; ch < 2; ++ch) lossFilter[ch]->prepare ((float) sampleRate, samplesPerBlock); @@ -169,6 +172,7 @@ void ChowtapeModelAudioProcessor::processBlock (AudioBuffer<float>& buffer, Midi inGain.processBlock (buffer, midiMessages); hysteresis.processBlock (buffer, midiMessages); degrade.processBlock (buffer, midiMessages); + chewer.processBlock (buffer); flutter.processBlock (buffer, midiMessages); diff --git a/Plugin/Source/PluginProcessor.h b/Plugin/Source/PluginProcessor.h @@ -16,6 +16,7 @@ #include "Processors/Loss_Effects/LossFilter.h" #include "Processors/Timing_Effects/Flutter.h" #include "Processors/Degrade/DegradeProcessor.h" +#include "Processors/Chew/ChewProcessor.h" //============================================================================== /** @@ -69,6 +70,7 @@ private: GainProcessor inGain; HysteresisProcessor hysteresis; DegradeProcessor degrade; + ChewProcessor chewer; std::unique_ptr<LossFilter> lossFilter[2]; Flutter flutter; GainProcessor outGain; diff --git a/Plugin/Source/Processors/Chew/ChewProcessor.cpp b/Plugin/Source/Processors/Chew/ChewProcessor.cpp @@ -0,0 +1,56 @@ +#include "ChewProcessor.h" + +ChewProcessor::ChewProcessor (AudioProcessorValueTreeState& vts) +{ + depth = vts.getRawParameterValue ("chew_depth"); + freq = vts.getRawParameterValue ("chew_freq"); +} + +void ChewProcessor::createParameterLayout (std::vector<std::unique_ptr<RangedAudioParameter>>& params) +{ + params.push_back (std::make_unique<AudioParameterFloat> ("chew_depth", "Depth", 0.0f, 1.0f, 0.0f)); + params.push_back (std::make_unique<AudioParameterFloat> ("chew_freq", "Freq", 0.0f, 1.0f, 0.0f)); +} + +void ChewProcessor::prepare (double sr, int samplesPerBlock) +{ + sampleRate = (float) sr; + + dropout.prepare (samplesPerBlock); + + isCrinkled = false; + samplesUntilChange = getDryTime(); + sampleCounter = 0; +} + +void ChewProcessor::processBlock (AudioBuffer<float>& buffer) +{ + if (*depth == 0.0f) + return; + + if (sampleCounter >= samplesUntilChange) + { + sampleCounter = 0; + isCrinkled = ! isCrinkled; + + if (isCrinkled) // start crinkle + { + mix = 1.0f; + power = 0.5f; //depth->control->get(); + samplesUntilChange = getWetTime(); + } + else // end crinkle + { + mix = 0.0f; + power = 0.0f; + samplesUntilChange = getDryTime(); + } + } + + dropout.setMix (mix); + dropout.setPow (1.0f + 4.0f * power); + + dropout.process (buffer); + + sampleCounter += buffer.getNumSamples(); +} diff --git a/Plugin/Source/Processors/Chew/ChewProcessor.h b/Plugin/Source/Processors/Chew/ChewProcessor.h @@ -0,0 +1,45 @@ +#ifndef CHEWPROCESSOR_H_INCLUDED +#define CHEWPROCESSOR_H_INCLUDED + +#include "Dropout.h" + +class ChewProcessor +{ +public: + ChewProcessor (AudioProcessorValueTreeState& vts); + + static void createParameterLayout (std::vector<std::unique_ptr<RangedAudioParameter>>& params); + + void prepare (double sr, int samplesPerBlock); + void processBlock (AudioBuffer<float>& buffer); + +private: + float* depth = nullptr; + float* freq = nullptr; + + float mix = 0.0f; + float power = 0.0f; + + Dropout dropout; + + Random random; + int samplesUntilChange = 1000; + bool isCrinkled = false; + int sampleCounter = 0; + + float sampleRate = 44100.0f; + + inline int getDryTime() + { + return random.nextInt (Range<int> ((int) ((1.0 - *freq) * sampleRate), (int) ((2 - 1.8 * *freq) * sampleRate))); + } + + inline int getWetTime() + { + return random.nextInt (Range<int> ((int) ((0.05 + 0.05f * *depth) * sampleRate), (int) ((0.8 + 0.8 * *depth) * sampleRate))); + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChewProcessor) +}; + +#endif // CHEWPROCESSOR_H_INCLUDED diff --git a/Plugin/Source/Processors/Chew/Dropout.h b/Plugin/Source/Processors/Chew/Dropout.h @@ -0,0 +1,75 @@ +#ifndef DROPOUT_H_INCLUDED +#define DROPOUT_H_INCLUDED + +#include "JuceHeader.h" + +class Dropout +{ +public: + Dropout() {} + + void setMix (float newMix) { curMix = newMix; } + void setPow (float newPow) { power = newPow; } + + void prepare (int maxBufferSize) + { + dryBuffer.setSize (2, maxBufferSize); + + prevMix = curMix; + } + + void process (AudioBuffer<float>& buffer) + { + if (curMix == 0.0f) + return; + + // copy dry buffer + for (int ch = 0; ch < buffer.getNumChannels(); ++ch) + { + dryBuffer.copyFrom (ch, 0, buffer.getReadPointer (ch), buffer.getNumSamples()); + + auto* x = buffer.getWritePointer (ch); + for (int n = 0; n < buffer.getNumSamples(); ++n) + x[n] = dropout (x[n]); + } + + if (curMix == prevMix) + { + buffer.applyGain (curMix); + + for (int ch = 0; ch < buffer.getNumChannels(); ++ch) + buffer.addFrom (ch, 0, dryBuffer.getReadPointer (ch), buffer.getNumSamples(), (1.0f - curMix)); + } + else + { + buffer.applyGainRamp (0, buffer.getNumSamples(), prevMix, curMix); + + for (int ch = 0; ch < buffer.getNumChannels(); ++ch) + buffer.addFromWithRamp (ch, 0, dryBuffer.getReadPointer (ch), buffer.getNumSamples(), (1.0f - prevMix), (1.0f - curMix)); + + prevMix = curMix; + } + } + + inline float dropout (float x) + { + float sign = 0.0f; + if (x < 0.0f) + sign = -1.0f; + else if (x > 0.0f) + sign = 1.0f; + + return std::powf (abs (x), power) * sign / power; + } + +private: + float curMix = 0.0f; + float prevMix = curMix; + float power = 1.0f; + + AudioBuffer<float> dryBuffer; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Dropout) +}; + +#endif // DROPOUT_H_INCLUDED diff --git a/Plugin/Source/gui.xml b/Plugin/Source/gui.xml Binary files differ.