#ifndef __Oscillator_h
#define __Oscillator_h
#include "basicmaths.h"
#include "FloatArray.h"
#include "SignalGenerator.h"
class Oscillator : public SignalGenerator {
public:
Oscillator(){}
virtual ~Oscillator(){}
using SignalGenerator::generate;
virtual void setSampleRate(float value){}
virtual void setFrequency(float value) = 0;
virtual float getFrequency() = 0;
virtual void setPhase(float phase) = 0;
virtual float getPhase() = 0;
virtual void reset() = 0;
virtual float generate(float fm) = 0;
virtual void generate(FloatArray output, FloatArray fm){
for(size_t i=0; i<output.getSize(); ++i)
output[i] = generate(fm[i]);
}
[[deprecated("use generate() instead.")]]
float getNextSample(){ return generate(); }
[[deprecated("use generate() instead.")]]
float getNextSample(float fm){ return generate(fm); }
[[deprecated("use generate() instead.")]]
void getSamples(FloatArray output){
generate(output);
}
[[deprecated("use generate() instead.")]]
void getSamples(FloatArray output, FloatArray fm){
generate(output, fm);
}
};
template<class T, class BaseOscillator=Oscillator, typename Sample=float>
class OscillatorTemplate : public BaseOscillator {
protected:
float mul = 1; float phase = 0;
float incr = 0;
public:
void setSampleRate(float sr){
float freq = getFrequency();
mul = (T::end_phase - T::begin_phase)/sr;
setFrequency(freq);
}
float getSampleRate(){
return (T::end_phase - T::begin_phase)/mul;
}
void setFrequency(float freq){
incr = freq*mul;
}
float getFrequency(){
return incr/mul;
}
void setPhase(float ph){
phase = (T::end_phase - T::begin_phase)*ph/(2*M_PI) + T::begin_phase;
}
float getPhase(){
return (phase - T::begin_phase)*2*M_PI/(T::end_phase - T::begin_phase);
}
void reset(){
phase = T::begin_phase;
}
Sample generate() {
Sample sample = static_cast<T*>(this)->getSample();
phase += incr;
if(phase >= T::end_phase)
phase -= (T::end_phase - T::begin_phase);
return sample;
}
Sample generate(float fm) {
Sample sample = static_cast<T*>(this)->getSample();
phase += incr + (T::end_phase - T::begin_phase)*fm;
if(phase >= T::end_phase)
phase -= (T::end_phase - T::begin_phase);
return sample;
}
using BaseOscillator::generate;
static T* create(float sr){
T* obj = new T();
obj->setSampleRate(sr);
return obj;
}
static void destroy(T* osc){
delete osc;
}
protected:
static float polyblep(float t, float dt){
if(t < dt){
t /= dt;
return t+t - t*t - 1;
}else if(t + dt > 1){
t = (t - 1) / dt;
return t*t + t+t + 1;
}
return 0;
}
};
template<class Osc>
class PhaseShiftOscillator : public Osc {
protected:
float phaseshift;
public:
template <typename... Args>
PhaseShiftOscillator(float phaseshift, Args&&... args) :
Osc(std::forward<Args>(args)...), phaseshift(phaseshift) {}
void setPhase(float phase){
Osc::setPhase(phase + phaseshift);
}
float getPhase(){
return Osc::getPhase() - phaseshift;
}
void reset(){
Osc::setPhase(phaseshift);
}
template <typename... Args>
static PhaseShiftOscillator<Osc>* create(float phaseshift, Args&&... args){
return new PhaseShiftOscillator<Osc>(phaseshift, std::forward<Args>(args)...);
}
static void destroy(PhaseShiftOscillator<Osc>* obj){
Osc::destroy(obj);
}
};
#endif