From e10c60004fa6ef4337f1325d329fd66e139c337b Mon Sep 17 00:00:00 2001 From: Barabas Raffai Date: Fri, 14 Jun 2019 13:32:34 +0100 Subject: [PATCH] init --- .gitignore | 3 + Source/Clipping.cpp | 29 +++++++ Source/Clipping.h | 30 +++++++ Source/Contour.cpp | 11 +++ Source/Contour.h | 11 +++ Source/FMV.cpp | 11 +++ Source/FMV.h | 11 +++ Source/GainControl.cpp | 11 +++ Source/GainControl.h | 11 +++ Source/InputFilter.cpp | 11 +++ Source/InputFilter.h | 11 +++ Source/PluginEditor.cpp | 42 +++++++++ Source/PluginEditor.h | 35 ++++++++ Source/PluginProcessor.cpp | 174 +++++++++++++++++++++++++++++++++++++ Source/PluginProcessor.h | 63 ++++++++++++++ Source/WaveShape.cpp | 58 +++++++++++++ Source/WaveShape.h | 4 + valvestate.jucer | 76 ++++++++++++++++ 18 files changed, 602 insertions(+) create mode 100644 .gitignore create mode 100644 Source/Clipping.cpp create mode 100644 Source/Clipping.h create mode 100644 Source/Contour.cpp create mode 100644 Source/Contour.h create mode 100644 Source/FMV.cpp create mode 100644 Source/FMV.h create mode 100644 Source/GainControl.cpp create mode 100644 Source/GainControl.h create mode 100644 Source/InputFilter.cpp create mode 100644 Source/InputFilter.h create mode 100644 Source/PluginEditor.cpp create mode 100644 Source/PluginEditor.h create mode 100644 Source/PluginProcessor.cpp create mode 100644 Source/PluginProcessor.h create mode 100644 Source/WaveShape.cpp create mode 100644 Source/WaveShape.h create mode 100644 valvestate.jucer diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34aad73 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +Builds/ +JuceLibraryCode/ +compile_commands.json diff --git a/Source/Clipping.cpp b/Source/Clipping.cpp new file mode 100644 index 0000000..4b4105e --- /dev/null +++ b/Source/Clipping.cpp @@ -0,0 +1,29 @@ +#include "Clipping.h" +#define OVERSAMPLING_ORDER 3 + +Clipping::Clipping() : oversampling(1, OVERSAMPLING_ORDER, + dsp::Oversampling::filterHalfBandPolyphaseIIR) +{ + waveshaper.functionToUse = waveshape; +} + +Clipping::~Clipping() {} + +void Clipping::process(dsp::AudioBlock block) +{ + auto oversampledBlock = oversampling.processSamplesUp(block); + + dsp::ProcessContextReplacing ctx(oversampledBlock); + waveshaper.process(ctx); + + oversampling.processSamplesDown(block); +} +void Clipping::prepare(dsp::ProcessSpec spec) +{ + oversampling.initProcessing(spec.maximumBlockSize); +} + +void Clipping::reset() +{ + oversampling.reset(); +} diff --git a/Source/Clipping.h b/Source/Clipping.h new file mode 100644 index 0000000..ed6ba7d --- /dev/null +++ b/Source/Clipping.h @@ -0,0 +1,30 @@ +/* + ============================================================================== + + Clipping.h + Created: 14 Jun 2019 9:46:07am + Author: barabas + + ============================================================================== +*/ + +#pragma once +#include "../JuceLibraryCode/JuceHeader.h" +#include "WaveShape.h" + +class Clipping +{ + public: + Clipping(); + ~Clipping(); + + void process(dsp::AudioBlock block); + void prepare(dsp::ProcessSpec spec); + void reset(); + + private: + dsp::WaveShaper waveshaper; + dsp::Oversampling oversampling; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Clipping); +}; diff --git a/Source/Contour.cpp b/Source/Contour.cpp new file mode 100644 index 0000000..60c752e --- /dev/null +++ b/Source/Contour.cpp @@ -0,0 +1,11 @@ +/* + ============================================================================== + + Contour.cpp + Created: 14 Jun 2019 9:46:54am + Author: barabas + + ============================================================================== +*/ + +#include "Contour.h" diff --git a/Source/Contour.h b/Source/Contour.h new file mode 100644 index 0000000..fce6353 --- /dev/null +++ b/Source/Contour.h @@ -0,0 +1,11 @@ +/* + ============================================================================== + + Contour.h + Created: 14 Jun 2019 9:46:54am + Author: barabas + + ============================================================================== +*/ + +#pragma once diff --git a/Source/FMV.cpp b/Source/FMV.cpp new file mode 100644 index 0000000..68c7516 --- /dev/null +++ b/Source/FMV.cpp @@ -0,0 +1,11 @@ +/* + ============================================================================== + + FMV.cpp + Created: 14 Jun 2019 9:45:03am + Author: barabas + + ============================================================================== +*/ + +#include "FMV.h" diff --git a/Source/FMV.h b/Source/FMV.h new file mode 100644 index 0000000..50bc806 --- /dev/null +++ b/Source/FMV.h @@ -0,0 +1,11 @@ +/* + ============================================================================== + + FMV.h + Created: 14 Jun 2019 9:45:03am + Author: barabas + + ============================================================================== +*/ + +#pragma once diff --git a/Source/GainControl.cpp b/Source/GainControl.cpp new file mode 100644 index 0000000..b804bcb --- /dev/null +++ b/Source/GainControl.cpp @@ -0,0 +1,11 @@ +/* + ============================================================================== + + GainControl.cpp + Created: 14 Jun 2019 9:45:31am + Author: barabas + + ============================================================================== +*/ + +#include "GainControl.h" diff --git a/Source/GainControl.h b/Source/GainControl.h new file mode 100644 index 0000000..75665ab --- /dev/null +++ b/Source/GainControl.h @@ -0,0 +1,11 @@ +/* + ============================================================================== + + GainControl.h + Created: 14 Jun 2019 9:45:31am + Author: barabas + + ============================================================================== +*/ + +#pragma once diff --git a/Source/InputFilter.cpp b/Source/InputFilter.cpp new file mode 100644 index 0000000..84fc99d --- /dev/null +++ b/Source/InputFilter.cpp @@ -0,0 +1,11 @@ +/* + ============================================================================== + + InputFilter.cpp + Created: 14 Jun 2019 9:45:24am + Author: barabas + + ============================================================================== +*/ + +#include "InputFilter.h" diff --git a/Source/InputFilter.h b/Source/InputFilter.h new file mode 100644 index 0000000..4bd86a8 --- /dev/null +++ b/Source/InputFilter.h @@ -0,0 +1,11 @@ +/* + ============================================================================== + + InputFilter.h + Created: 14 Jun 2019 9:45:24am + Author: barabas + + ============================================================================== +*/ + +#pragma once diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp new file mode 100644 index 0000000..9afc396 --- /dev/null +++ b/Source/PluginEditor.cpp @@ -0,0 +1,42 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for a JUCE plugin editor. + + ============================================================================== +*/ + +#include "PluginProcessor.h" +#include "PluginEditor.h" + +//============================================================================== +ValvestateAudioProcessorEditor::ValvestateAudioProcessorEditor (ValvestateAudioProcessor& p) + : AudioProcessorEditor (&p), processor (p) +{ + // Make sure that before the constructor has finished, you've set the + // editor's size to whatever you need it to be. + setSize (400, 300); +} + +ValvestateAudioProcessorEditor::~ValvestateAudioProcessorEditor() +{ +} + +//============================================================================== +void ValvestateAudioProcessorEditor::paint (Graphics& g) +{ + // (Our component is opaque, so we must completely fill the background with a solid colour) + g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId)); + + g.setColour (Colours::white); + g.setFont (15.0f); + g.drawFittedText ("Hello World!", getLocalBounds(), Justification::centred, 1); +} + +void ValvestateAudioProcessorEditor::resized() +{ + // This is generally where you'll want to lay out the positions of any + // subcomponents in your editor.. +} diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h new file mode 100644 index 0000000..dab0adc --- /dev/null +++ b/Source/PluginEditor.h @@ -0,0 +1,35 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for a JUCE plugin editor. + + ============================================================================== +*/ + +#pragma once + +#include "../JuceLibraryCode/JuceHeader.h" +#include "PluginProcessor.h" + +//============================================================================== +/** +*/ +class ValvestateAudioProcessorEditor : public AudioProcessorEditor +{ +public: + ValvestateAudioProcessorEditor (ValvestateAudioProcessor&); + ~ValvestateAudioProcessorEditor(); + + //============================================================================== + void paint (Graphics&) override; + void resized() override; + +private: + // This reference is provided as a quick way for your editor to + // access the processor object that created it. + ValvestateAudioProcessor& processor; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValvestateAudioProcessorEditor) +}; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp new file mode 100644 index 0000000..60a31a6 --- /dev/null +++ b/Source/PluginProcessor.cpp @@ -0,0 +1,174 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for a JUCE plugin processor. + + ============================================================================== +*/ + +#include "PluginProcessor.h" +#include "PluginEditor.h" + +//============================================================================== +ValvestateAudioProcessor::ValvestateAudioProcessor() +#ifndef JucePlugin_PreferredChannelConfigurations + : AudioProcessor (BusesProperties() + #if ! JucePlugin_IsMidiEffect + #if ! JucePlugin_IsSynth + .withInput ("Input", AudioChannelSet::stereo(), true) + #endif + .withOutput ("Output", AudioChannelSet::stereo(), true) + #endif + ) +#endif +{ +} + +ValvestateAudioProcessor::~ValvestateAudioProcessor() +{ +} + +//============================================================================== +const String ValvestateAudioProcessor::getName() const +{ + return JucePlugin_Name; +} + +bool ValvestateAudioProcessor::acceptsMidi() const +{ + #if JucePlugin_WantsMidiInput + return true; + #else + return false; + #endif +} + +bool ValvestateAudioProcessor::producesMidi() const +{ + #if JucePlugin_ProducesMidiOutput + return true; + #else + return false; + #endif +} + +bool ValvestateAudioProcessor::isMidiEffect() const +{ + #if JucePlugin_IsMidiEffect + return true; + #else + return false; + #endif +} + +double ValvestateAudioProcessor::getTailLengthSeconds() const +{ + return 0.0; +} + +int ValvestateAudioProcessor::getNumPrograms() +{ + return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs, + // so this should be at least 1, even if you're not really implementing programs. +} + +int ValvestateAudioProcessor::getCurrentProgram() +{ + return 0; +} + +void ValvestateAudioProcessor::setCurrentProgram (int index) +{ +} + +const String ValvestateAudioProcessor::getProgramName (int index) +{ + return {}; +} + +void ValvestateAudioProcessor::changeProgramName (int index, const String& newName) +{ +} + +//============================================================================== +void ValvestateAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) +{ + dsp::ProcessSpec spec; + spec.sampleRate = sampleRate; + spec.maximumBlockSize = samplesPerBlock; + spec.numChannels = 1; + + clipping.prepare(spec); +} + +void ValvestateAudioProcessor::releaseResources() +{ + clipping.reset(); +} + +#ifndef JucePlugin_PreferredChannelConfigurations +bool ValvestateAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const +{ + #if JucePlugin_IsMidiEffect + ignoreUnused (layouts); + return true; + #else + // This is the place where you check if the layout is supported. + // In this template code we only support mono or stereo. + if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono() + && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo()) + return false; + + // This checks if the input layout matches the output layout + #if ! JucePlugin_IsSynth + if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) + return false; + #endif + + return true; + #endif +} +#endif + +void ValvestateAudioProcessor::processBlock (AudioBuffer& buffer, MidiBuffer& midiMessages) +{ + ScopedNoDenormals noDenormals; + + dsp::AudioBlock block(buffer); + + clipping.process(block); +} + +//============================================================================== +bool ValvestateAudioProcessor::hasEditor() const +{ + return true; // (change this to false if you choose to not supply an editor) +} + +AudioProcessorEditor* ValvestateAudioProcessor::createEditor() +{ + return new ValvestateAudioProcessorEditor (*this); +} + +//============================================================================== +void ValvestateAudioProcessor::getStateInformation (MemoryBlock& destData) +{ + // You should use this method to store your parameters in the memory block. + // You could do that either as raw data, or use the XML or ValueTree classes + // as intermediaries to make it easy to save and load complex data. +} + +void ValvestateAudioProcessor::setStateInformation (const void* data, int sizeInBytes) +{ + // You should use this method to restore your parameters from this memory block, + // whose contents will have been created by the getStateInformation() call. +} + +//============================================================================== +// This creates new instances of the plugin.. +AudioProcessor* JUCE_CALLTYPE createPluginFilter() +{ + return new ValvestateAudioProcessor(); +} diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h new file mode 100644 index 0000000..d70423e --- /dev/null +++ b/Source/PluginProcessor.h @@ -0,0 +1,63 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for a JUCE plugin processor. + + ============================================================================== +*/ + +#pragma once + +#include "../JuceLibraryCode/JuceHeader.h" +#include "Clipping.h" + +//============================================================================== +/** +*/ +class ValvestateAudioProcessor : public AudioProcessor +{ +public: + //============================================================================== + ValvestateAudioProcessor(); + ~ValvestateAudioProcessor(); + + //============================================================================== + void prepareToPlay (double sampleRate, int samplesPerBlock) override; + void releaseResources() override; + + #ifndef JucePlugin_PreferredChannelConfigurations + bool isBusesLayoutSupported (const BusesLayout& layouts) const override; + #endif + + void processBlock (AudioBuffer&, MidiBuffer&) override; + + //============================================================================== + AudioProcessorEditor* createEditor() override; + bool hasEditor() const override; + + //============================================================================== + const String getName() const override; + + bool acceptsMidi() const override; + bool producesMidi() const override; + bool isMidiEffect() const override; + double getTailLengthSeconds() const override; + + //============================================================================== + int getNumPrograms() override; + int getCurrentProgram() override; + void setCurrentProgram (int index) override; + const String getProgramName (int index) override; + void changeProgramName (int index, const String& newName) override; + + //============================================================================== + void getStateInformation (MemoryBlock& destData) override; + void setStateInformation (const void* data, int sizeInBytes) override; + +private: + //============================================================================== + Clipping clipping; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValvestateAudioProcessor) +}; diff --git a/Source/WaveShape.cpp b/Source/WaveShape.cpp new file mode 100644 index 0000000..78a0eca --- /dev/null +++ b/Source/WaveShape.cpp @@ -0,0 +1,58 @@ +#include "WaveShape.h" +#include + +const float shape[100] = { + 260.874 , 260.36155152, 259.68101616, 258.83249394, 258.12373131, + 257.32490505, 256.30403636, 255.30199798, 254.34203232, 253.08117273, + 251.64408485, 250.62568889, 249.36276061, 247.85529798, 245.82016162, + 243.16351212, 239.88231717, 237.3534798 , 235.59948182, 233.75043737, + 231.81578283, 230.6437697 , 229.62558889, 228.59006869, 227.53750909, + 226.46871717, 225.38408687, 224.28356364, 222.27520101, 219.96075758, + 217.55801212, 216.27730909, 214.99263636, 213.66246667, 212.28120808, + 210.84921515, 209.37504545, 207.87093333, 206.3475404 , 204.81160303, + 203.2669899 , 201.43521919, 197.36075758, 193.30988586, 189.22967778, + 185.12009091, 180.98376869, 176.82380606, 172.64047273, 169.22337879, + 166.17794545, 163.12334848, 159.32633939, 155.88505556, 152.5707 , + 149.25255556, 145.93375152, 142.61785152, 139.30987273, 137.36382626, + 135.72008182, 134.08206162, 132.45135758, 130.82926364, 129.21729596, + 127.21884545, 124.0715 , 121.00046061, 118.0256899 , 115.17009697, + 112.45427374, 109.70993535, 106.19916364, 103.49122626, 102.10980404, + 100.81236667, 99.59889232, 98.08463889, 97.36694788, 96.69223283, + 96.06147778, 95.47537636, 94.93400081, 94.24110576, 93.39900939, + 92.42075859, 91.82170939, 91.30980818, 90.88505333, 89.66791747, + 88.56323182, 87.84395242, 87.30069909, 86.73431242, 86.28330707, + 85.9333599 , 85.61168818, 85.32950929, 85.08680323, 85.06124 +}; + +const int shape_size = 100; + +float waveshape(float input) +{ + float output; + //if input is out of range, hard clip + //TODO: maybe it's better if we follow the gradient at the end of the shape + if(input <= -1) + { + output = shape[0]; + } + else if(input >= 1) + { + output = shape[shape_size - 1]; + } + else + { + //calculate which sample of shape the input sample corresponds to + //the first sample is -1, last is 1 + float index = (input + 1.0f)/2.0f * (shape_size-1); + + //linear interpolation + //find ratio of x + float ratio = (index-floor(index)) / (ceil(index)-floor(index)); + + //y = c + mx + output = shape[(int)floor(index)] + + ratio*(shape[(int)ceil(index)]-shape[(int)floor(index)]); + } + + return output/300.0f; +} diff --git a/Source/WaveShape.h b/Source/WaveShape.h new file mode 100644 index 0000000..107d38d --- /dev/null +++ b/Source/WaveShape.h @@ -0,0 +1,4 @@ +#pragma once + +//waveshape extrated from spice simulation +float waveshape(float input); diff --git a/valvestate.jucer b/valvestate.jucer new file mode 100644 index 0000000..3b929d7 --- /dev/null +++ b/valvestate.jucer @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +