|
| 1 | +#ifndef __MorphingOscillator_h |
| 2 | +#define __MorphingOscillator_h |
| 3 | + |
| 4 | +#include "Oscillator.h" |
| 5 | + |
| 6 | +/** |
| 7 | + * The MorphingOscillator wraps a fixed number of Oscillators and crossfades |
| 8 | + * between their outputs. |
| 9 | + * Only two oscillator outputs are computed at a time. When changing between |
| 10 | + * crossfading oscillators, their phases are synchronised. |
| 11 | + */ |
| 12 | +class MorphingOscillator : public Oscillator { |
| 13 | +protected: |
| 14 | + Oscillator** osc; |
| 15 | + size_t osc_count; |
| 16 | + Oscillator* lo = NULL; |
| 17 | + Oscillator* hi = NULL; |
| 18 | + float xf = 0; |
| 19 | +public: |
| 20 | + MorphingOscillator(Oscillator** osc, size_t count) |
| 21 | + : osc(osc), osc_count(count){} |
| 22 | + void setFrequency(float value){ |
| 23 | + lo->setFrequency(value); |
| 24 | + hi->setFrequency(value); |
| 25 | + } |
| 26 | + float getFrequency(){ |
| 27 | + return lo->getFrequency(); |
| 28 | + } |
| 29 | + void setPhase(float value){ |
| 30 | + lo->setPhase(value); |
| 31 | + hi->setPhase(value); |
| 32 | + } |
| 33 | + float getPhase(){ |
| 34 | + return lo->getPhase(); |
| 35 | + } |
| 36 | + void reset(){ |
| 37 | + lo->reset(); |
| 38 | + hi->reset(); |
| 39 | + } |
| 40 | + float generate(){ |
| 41 | + float l = lo->generate(); |
| 42 | + float h = hi->generate(); |
| 43 | + return l + (h - l) * xf; |
| 44 | + } |
| 45 | + float generate(float fm){ |
| 46 | + float l = lo->generate(fm); |
| 47 | + float h = hi->generate(fm); |
| 48 | + return l + (h - l) * xf; |
| 49 | + } |
| 50 | + using Oscillator::generate; |
| 51 | + /** |
| 52 | + * Morph between all configured oscillators. |
| 53 | + * @param value a cross fade index between 0 and 1. |
| 54 | + */ |
| 55 | + void morph(float value){ |
| 56 | + value *= osc_count - 1; |
| 57 | + size_t idx = clamp((size_t)value, (size_t)0, osc_count - 2); |
| 58 | + Oscillator* newlo = osc[idx]; |
| 59 | + Oscillator* newhi = osc[idx+1]; |
| 60 | + xf = value - idx; |
| 61 | + if(lo != newlo){ |
| 62 | + newlo->setPhase(getPhase()); |
| 63 | + newlo->setFrequency(getFrequency()); |
| 64 | + lo = newlo; |
| 65 | + } |
| 66 | + if(hi != newhi){ |
| 67 | + newhi->setPhase(getPhase()); |
| 68 | + newhi->setFrequency(getFrequency()); |
| 69 | + hi = newhi; |
| 70 | + } |
| 71 | + } |
| 72 | + size_t getNumberOfOscillators(){ |
| 73 | + return osc_count; |
| 74 | + } |
| 75 | + Oscillator* getOscillator(size_t index){ |
| 76 | + return osc[index]; |
| 77 | + } |
| 78 | + void setOscillator(size_t index, Oscillator* oscillator){ |
| 79 | + osc[index] = oscillator; |
| 80 | + lo = hi; |
| 81 | + hi = oscillator; |
| 82 | + } |
| 83 | + static MorphingOscillator* create(size_t oscillator_count){ |
| 84 | + return new MorphingOscillator(new Oscillator*[oscillator_count], oscillator_count); |
| 85 | + } |
| 86 | + static void destroy(MorphingOscillator* obj){ |
| 87 | + delete[] obj->osc; |
| 88 | + delete obj; |
| 89 | + } |
| 90 | +}; |
| 91 | + |
| 92 | +#endif /* __MorphingOscillator_h */ |
0 commit comments