1 /*
2 ** Surge Synthesizer is Free and Open Source Software
3 **
4 ** Surge is made available under the Gnu General Public License, v3.0
5 ** https://www.gnu.org/licenses/gpl-3.0.en.html
6 **
7 ** Copyright 2004-2021 by various individuals as described by the Git transaction log
8 **
9 ** All source at: https://github.com/surge-synthesizer/surge.git
10 **
11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership
12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge
13 ** open source in September 2018.
14 */
15 
16 #include "OscillatorBase.h"
17 #include "DspUtilities.h"
18 #include "OscillatorCommonFunctions.h"
19 
20 class AliasOscillator : public Oscillator
21 {
22   public:
23     enum ao_params
24     {
25         ao_wave = 0,
26         ao_wrap,
27         ao_mask,
28         ao_threshold,
29         ao_bit_depth,
30 
31         ao_unison_detune = 5,
32         ao_unison_voices,
33     };
34 
35     enum ao_waves
36     {
37         aow_sine,
38         aow_ramp,
39         aow_pulse,
40         aow_noise,
41 
42         aow_mem_alias,
43         aow_mem_oscdata,
44         aow_mem_scenedata,
45         aow_mem_dawextra,
46         aow_mem_stepseqdata,
47 
48         aow_audiobuffer,
49 
50         aow_sine_tx2,
51         aow_sine_tx3,
52         aow_sine_tx4,
53         aow_sine_tx5,
54         aow_sine_tx6,
55         aow_sine_tx7,
56         aow_sine_tx8,
57 
58         aow_additive,
59 
60         ao_n_waves
61     };
62 
63     static constexpr int n_additive_partials = 16;
64 
AliasOscillator(SurgeStorage * s,OscillatorStorage * o,pdata * p)65     AliasOscillator(SurgeStorage *s, OscillatorStorage *o, pdata *p) : Oscillator(s, o, p)
66     {
67         for (auto u = 0; u < MAX_UNISON; ++u)
68         {
69             phase[u] = 0;
70             mixL[u] = 1.f;
71             mixR[u] = 1.f;
72         }
73     }
74 
75     virtual void init(float pitch, bool is_display = false, bool nonzero_init_drift = true);
init_ctrltypes(int scene,int oscnum)76     virtual void init_ctrltypes(int scene, int oscnum) { init_ctrltypes(); };
77     virtual void init_ctrltypes();
78     virtual void init_default_values();
init_extra_config()79     virtual void init_extra_config()
80     {
81         oscdata->extraConfig.nData = 16;
82         for (auto i = 0; i < oscdata->extraConfig.nData; ++i)
83             oscdata->extraConfig.data[i] = 1.f / (i + 1);
84     }
85     virtual void process_block(float pitch, float drift = 0.f, bool stereo = false, bool FM = false,
86                                float FMdepth = 0.f);
87     template <bool do_FM, bool do_bitcrush, AliasOscillator::ao_waves wavetype>
88     void process_block_internal(const float pitch, const float drift, const bool stereo,
89                                 const float fmdepthV, const float crush_bits);
90 
91     lag<float, true> fmdepth;
92 
93     // character filter
94     Surge::Oscillator::CharacterFilter<float> charFilt;
95 
96     int n_unison = 1;
97     uint32_t phase[MAX_UNISON];
98     float unisonOffsets[MAX_UNISON];
99     float mixL[MAX_UNISON], mixR[MAX_UNISON];
100     uint8_t dynamic_wavetable[256];
101     unsigned dynamic_wavetable_sleep = 0; // blocks to wait before recalculating dynamic wavetable
102 
103     struct UInt8RNG
104     {
105         // Based on http://en.wikipedia.org/wiki/Xorshift
106         // and inspired by https://github.com/edrosten/8bit_rng and
107         // http://www.donnelly-house.net/programming/cdp1802/8bitPRNGtest.html
108 
109         uint8_t x, y, z, a;
110         uint8_t stepCount;
UInt8RNGUInt8RNG111         UInt8RNG() : x(21), y(229), z(181), a(rand() & 0xFF), stepCount(0) {}
112 
stepUInt8RNG113         inline uint8_t step()
114         {
115             uint8_t t = x ^ ((x << 3U) & 0xFF);
116             x = y;
117             y = z;
118             z = a;
119             a = a ^ (a >> 5U) ^ (t ^ (t >> 2U));
120             return a;
121         }
stepToUInt8RNG122         inline uint8_t stepTo(uint8_t sc, uint8_t every)
123         {
124             uint8_t r = a;
125             while (stepCount != sc)
126             {
127                 stepCount++;
128                 if (stepCount % every == 0)
129                     r = step();
130             }
131             return r;
132         }
133     };
134     UInt8RNG urng8[MAX_UNISON];
135 
136     Surge::Oscillator::DriftLFO driftLFO[MAX_UNISON];
137 };
138 
139 struct Always255CountedSet
140     : public CountedSetUserData // Something to feed to a ct_countedset_percent control
141 {
getCountedSetSizeAlways255CountedSet142     virtual int getCountedSetSize() { return 255; }
143 };
144 
145 const Always255CountedSet ALWAYS255COUNTEDSET;
146 
147 extern const char *ao_type_names[];
148