/**************************************************************************
Copyright (C) 2019 Arnaud Champenois arthelion@free.fr
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
#include <juce_dsp/juce_dsp.h>
#include "WaveGenerator.h"
#include <string>
#include <thread>
#include "LFOModulated.h"
/*!
* Modulated wave generator.
* Contains a sine with harmonics, a square sub, a sawtooth and a modulated PWM
*
*/
class VCO : public LFOModulated {
public:
VCO(const VCOParameters&vcoParams) :
LFOModulated(vcoParams),mVCOParam(vcoParams) {
}
~VCO() {}
/*!
* Initializes the Wave Generators in 2 threads (for the first call).
*
* \param sampleRate Sample rate of audio flow
*/
void init(double sampleRate) override;
virtual void noteOn(int note) override;
/*!
* Generates a sample with a given input frequency
*
* \param freq The frequency (which can be modulated)
* \return The sample value
*/
double next(double freq) {
double value = 0.0;
double phaseShift = (RndPhaseSinCoef * mPhaseSineGenerator.next(mPhaseShiftFreq) +
RndPhaseNoiseCoef * mPhaseNoiseGenerator.next())*440.0;
freq = freq + mPhaseJitter * phaseShift;
// Sine generator
if (mSineGain != 0.0)
value += mSineGain*mSineGenerator.next(freq);
else
mSineGenerator.move(freq);
if (mHOddGain != 0.0)
value += mHOddGain * mHOddGenerator.next(freq);
else
mHOddGenerator.move(freq);
if (mHEvenGain != 0.0)
value += mHEvenGain * mHEvenGenerator.next(freq);
else
mHEvenGenerator.move(freq);
// Saw generator
if (mSawGain != 0.0) {
if(freq< mSawtoothGenerator.getSamplingFreq()*0.25)
value += mSawGain * mSawtoothGenerator.next(freq*2.0);
}
else
mSawtoothGenerator.move(freq*2.0); // keep the phase
// Sub generator
if (mSubGain != 0.0) {
value += mSubGain * mSubGenerator.next(freq*0.5);
}
else
mSubGenerator.move(freq); // keep the phase
// PWM square generator
if (mPWMGain != 0.0) {
if (!isLFOBypassed())
value += mPWMGain * mPWMGenerator.next(freq,mPWMRate*nextLFO());
else
value += mPWMGain * mPWMGenerator.next(freq, mPWMRate);
}
else
mPWMGenerator.move(freq); // keep the phase
if (mNoiseGain != 0.0)
value += mNoiseGain*mNoiseGenerator.next();
if (mSlope < 1.0) {
mSlope += 0.01;
value *= mSlope; // 100 samples of slope
}
return value;
}
virtual void updateInternalValues(int controller = 0) override;
void resetPhase();
private:
const VCOParameters&mVCOParam;
SineGenerator mSineGenerator;
OddHarmonicsGenerator mHOddGenerator;
EvenHarmonicsGenerator mHEvenGenerator;
SawToothGenerator mSawtoothGenerator;
SquareGenerator mSubGenerator;
PWMGenerator mPWMGenerator;
NoiseGenerator mNoiseGenerator;
NoiseGenerator mPhaseNoiseGenerator;
SineGenerator mPhaseSineGenerator;
double mSineGain = 1.0;
double mNoiseGain = 0.0;
double mSawGain = 0.0;
double mSubGain = 0.0;
double mPWMGain = 0.0;
double mPWMRate = 0.5;
double mSawPhase = 0.0;
double mSubPhase = 0.0;
double mPWMPhase = 0.0;
double mPhaseJitter = 0.0;
double mHOddGain = 0.0;
double mHEvenGain = 0.0;
double mSlope = 0.0;
double mPhaseShiftFreq = 0.01;
};