-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathPluginProcessor.cpp
More file actions
320 lines (255 loc) · 10.5 KB
/
PluginProcessor.cpp
File metadata and controls
320 lines (255 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
==============================================================================
This class describes the Audio Processing in Fuzzed.
==============================================================================
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
//Create the plugin instance
AudioProcessor* JUCE_CALLTYPE createPluginFilter();
//==============================================================================
FuzzFaceJuceAudioProcessor::FuzzFaceJuceAudioProcessor()
: volParam(nullptr),
fuzzParam(nullptr),
gainParam(nullptr)
{
//Instance of the simulation class, using scoped pointer to avoid memory leaking
sim = new Simulation(DEFAULT_SR, DEFAULT_VCC);
//Parameter smoothing
linFuzzSmoother = new LinearSmoothedValue<double>;
linVolSmoother = new LinearSmoothedValue<double>;
linGainSmoother = new LinearSmoothedValue<double>;
//Create the parameters
addParameter(gainParam = new AudioParameterFloat("gain", "Gain", GAIN_MIN, GAIN_MAX, GAIN_DEFAULT));
addParameter(volParam = new AudioParameterFloat("vol", "Vol", CTRL_MIN, CTRL_MAX, VOL_DEFAULT));
addParameter(fuzzParam = new AudioParameterFloat("fuzz", "Fuzz", CTRL_MIN, CTRL_MAX, CTRL_MIN));
//Sets the volVal and fuzzVal to defaults
gainVal = pow(10, (GAIN_DEFAULT/10)); //in dB
volVal = VOL_DEFAULT;
fuzzVal = FUZZ_DEFAULT;
//Sets the frequency for the timerCallback method to 1ms
startTimerHz(P_TIMER_FREQ);
//Default the samplerate
currentSampleRate = DEFAULT_SR;
//Set the smoothing times
linFuzzSmoother->reset(currentSampleRate/UPDATE_PARAM_MAJOR, SMOOTHING_TIME_S);
linVolSmoother->reset(currentSampleRate / UPDATE_PARAM_MAJOR, SMOOTHING_TIME_S);
linGainSmoother->reset(currentSampleRate / UPDATE_PARAM_MAJOR, SMOOTHING_TIME_S);
//update the param coeff
paramCoeff = exp(-2.0 * PI * (PARAM_CUTOFF / (currentSampleRate / UPDATE_PARAM_MAJOR)));
//Used to determine if the current sample is within the muted startup period
sampleIndex = 0;
}
FuzzFaceJuceAudioProcessor::~FuzzFaceJuceAudioProcessor()
{
}
//==============================================================================
const String FuzzFaceJuceAudioProcessor::getName() const
{
return JucePlugin_Name;
}
bool FuzzFaceJuceAudioProcessor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
return true;
#else
return false;
#endif
}
bool FuzzFaceJuceAudioProcessor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
return true;
#else
return false;
#endif
}
double FuzzFaceJuceAudioProcessor::getTailLengthSeconds() const
{
return 0.0;
}
int FuzzFaceJuceAudioProcessor::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 FuzzFaceJuceAudioProcessor::getCurrentProgram()
{
return 0;
}
void FuzzFaceJuceAudioProcessor::setCurrentProgram (int index)
{
}
const String FuzzFaceJuceAudioProcessor::getProgramName (int index)
{
return String();
}
void FuzzFaceJuceAudioProcessor::changeProgramName (int index, const String& newName)
{
}
//==============================================================================
void FuzzFaceJuceAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
}
void FuzzFaceJuceAudioProcessor::releaseResources()
{
// When playback stops, you can use this as an opportunity to free up any
// spare memory, etc.
}
#ifndef JucePlugin_PreferredChannelConfigurations
bool FuzzFaceJuceAudioProcessor::setPreferredBusArrangement (bool isInput, int bus, const AudioChannelSet& preferredSet)
{
// Reject any bus arrangements that are not compatible with your plugin
const int numChannels = preferredSet.size();
#if JucePlugin_IsMidiEffect
if (numChannels != 0)
return false;
#elif JucePlugin_IsSynth
if (isInput || (numChannels != 1 && numChannels != 2))
return false;
#else
if (numChannels != 1 && numChannels != 2)
return false;
if (! AudioProcessor::setPreferredBusArrangement (! isInput, bus, preferredSet))
return false;
#endif
return AudioProcessor::setPreferredBusArrangement (isInput, bus, preferredSet);
}
#endif
void FuzzFaceJuceAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
int numberOfSamples = buffer.getNumSamples();
//Declare the consts for number of channels
const int totalNumInputChannels = getTotalNumInputChannels();
const int totalNumOutputChannels = getTotalNumOutputChannels();
// In case we have more outputs than inputs, this code clears any output
// channels that didn't contain input data, (because these aren't
// guaranteed to be empty - they may contain garbage).
// This is here to avoid people getting screaming feedback
// when they first compile a plugin, but obviously you don't need to keep
// this code if your algorithm always overwrites all the output channels.
for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear(i, 0, buffer.getNumSamples());
//===========================================================================================
//If the sampleRate has changes then update the sim samplerate and clipping filter coeffs
if (currentSampleRate != getSampleRate()) {
currentSampleRate = getSampleRate();
//sets the simulation samplerate to current samplerate from DAW
sim->setSimSampleRate(currentSampleRate);
//update the smoothing times
linFuzzSmoother->reset(currentSampleRate/UPDATE_PARAM_MAJOR, SMOOTHING_TIME_S);
linVolSmoother->reset(currentSampleRate/UPDATE_PARAM_MAJOR, SMOOTHING_TIME_S);
linGainSmoother->reset(currentSampleRate/UPDATE_PARAM_MAJOR, SMOOTHING_TIME_S);
//update the param coeff
paramCoeff = exp(-2.0 * PI * (PARAM_CUTOFF / ((currentSampleRate) / UPDATE_PARAM_MAJOR)));
}
//===========================================================================================
//Process Samples
for (int index = 0; index < numberOfSamples; ++index)
{
//Check if fuzz or vol params have changed
if ((volVal != *volParam) || (fuzzVal != *fuzzParam)) {
//each UPDATE_PARAM_SAMPLE_INTERVAL, check the parameters changed and if so update
if (index % UPDATE_PARAM_MAJOR == 0) {
//every interval update the fuzz and vol val to the smoothed fuzz
fuzzVal = (*fuzzParam)*(1.0 - paramCoeff) + fuzzVal*paramCoeff;
volVal = (*volParam)*(1.0 - paramCoeff) + volVal*paramCoeff;
//Refresh the sim with new parameter values
sim->setParams(fuzzVal, volVal);
}
}
//Update the zipper matrices with smoothed coefficients each sample
sim->updateZipperMatrices();
//get the pointer to the channel data at the index
float* channelData = buffer.getWritePointer(0, index);
float* channelDataR = buffer.getWritePointer(1, index);
//Sum the channels to make mono
*channelData += *channelDataR;
//Get smoothed gain val
gainVal = linGainSmoother->getNextValue();
//Apply the input gain to the sample
*channelData *= gainVal;
//Update the variable for displaying the input signal label/meter
currentInput = abs(*channelData);
//Scale the signal for input to the system and clip the signal if outside allowable range
inputScaling(channelData);
//process the data
sim->processSample(channelData, DEFAULT_VCC);
//Scale the output signal back up to useable level
*channelData *= OUTPUT_SCALAR;
//Remove the pop by ramping up the output over STARTUP period of samples
if (sampleIndex < STARTUP) {
*channelData *= 1 / (STARTUP - sampleIndex);
sampleIndex++;
}
//Make both channels produce same output: ie convert back to "stereo"
*channelDataR = *channelData;
}
}
//===========================================================================================
//Scale the input, hard clip if the scaled input is still above the CLIPPING POINT, this
//stops the system from crashing when the input signal is too high
void FuzzFaceJuceAudioProcessor::inputScaling(float* _channelData) {
//Scale the input Signal
*_channelData *= MAX_INPUT_SIG * pow(2, -INPUT_SCALAR);
//Hard Clipping
//If signal is greater than max set it to max
if (*_channelData >= CLIPPING_POINT) {
*_channelData = CLIPPING_POINT;
}
else if (*_channelData <= -CLIPPING_POINT) {
*_channelData = -CLIPPING_POINT;
}
}
//Call this method at P_TIMER_FREQ hz to update the circuit param vals
void FuzzFaceJuceAudioProcessor::timerCallback()
{
//Every timer callback set the new target parameter val to the current setting on the knob
linFuzzSmoother->setValue(*fuzzParam);
linVolSmoother->setValue(*volParam);
//for decibel conversion
linGainSmoother->setValue(pow(10, (*gainParam / 10)));
}
//==============================================================================
bool FuzzFaceJuceAudioProcessor::hasEditor() const
{
return true; // (change this to false if you choose to not supply an editor)
}
AudioProcessorEditor* FuzzFaceJuceAudioProcessor::createEditor()
{
return new FuzzFaceJuceAudioProcessorEditor (*this);
}
//==============================================================================
void FuzzFaceJuceAudioProcessor::getStateInformation (MemoryBlock& destData)
{
//Create an XML element to store the parameter values
XmlElement xml("FUZZFACESETTINGS");
// Store the values of all our parameters, using their param ID as the XML attribute
for (int i = 0; i < getNumParameters(); ++i)
if (AudioProcessorParameterWithID* p = dynamic_cast<AudioProcessorParameterWithID*> (getParameters().getUnchecked(i)))
xml.setAttribute(p->paramID, p->getValue());
// then use this helper function to stuff it into the binary blob and return it..
copyXmlToBinary(xml, destData);
}
void FuzzFaceJuceAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
// This getXmlFromBinary() helper function retrieves our XML from the binary blob..
ScopedPointer<XmlElement> xmlState(getXmlFromBinary(data, sizeInBytes));
if (xmlState != nullptr)
{
// make sure that it's actually our type of XML object..
if (xmlState->hasTagName("FUZZFACESETTINGS"))
{
// reload the parameters
for (int i = 0; i < getNumParameters(); ++i)
if (AudioProcessorParameterWithID* p = dynamic_cast<AudioProcessorParameterWithID*> (getParameters().getUnchecked(i)))
p->setValueNotifyingHost((float)xmlState->getDoubleAttribute(p->paramID, p->getValue()));
}
}
}
//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new FuzzFaceJuceAudioProcessor();
}