-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathOscillator.h
More file actions
192 lines (157 loc) · 6 KB
/
Copy pathOscillator.h
File metadata and controls
192 lines (157 loc) · 6 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
#pragma once
#include "pluginconstants.h"
#include "synthfunctions.h"
#define OSC_FO_MOD_RANGE 2 //2 semitone default
#define OSC_HARD_SYNC_RATIO_RANGE 4 //
#define OSC_PITCHBEND_MOD_RANGE 12 //12 semitone default
#define OSC_FO_MIN 20 //20Hz
#define OSC_FO_MAX 20480 //20.480kHz = 10 octaves up from 20Hz
#define OSC_FO_DEFAULT 440.0 //A5
#define OSC_PULSEWIDTH_MIN 2 //2%
#define OSC_PULSEWIDTH_MAX 98 //98%
#define OSC_PULSEWIDTH_DEFAULT 50 //50%
class COscillator
{
public:
COscillator(void);
virtual ~COscillator(void);
// --- ATTRIBUTES
// --- PUBLIC: these variables may be get/set
// you may make get/set functions for them
// if you like, but will add function call layer
// --- oscillator run flag
bool m_bNoteOn;
// --- user controls or MIDI
double m_dOscFo; // oscillator frequency from MIDI note number
double m_dFoRatio; // FM Synth Modulator OR Hard Sync ratio
double m_dAmplitude; // 0->1 from GUI
// --- pulse width in % (sqr only) from GUI
double m_dPulseWidthControl;
// --- modulo counter and inc for timebase
double m_dModulo; // modulo counter 0->1
double m_dInc; // phase inc = fo/fs
// --- more pitch mods
int m_nOctave; // octave tweak
int m_nSemitones; // semitones tweak
int m_nCents; // cents tweak
// --- for PITCHED Oscillators
enum {SINE,SAW1,SAW2,SAW3,TRI,SQUARE,NOISE,PNOISE};
UINT m_uWaveform; // to store type
// --- for LFOs
enum {sine,usaw,dsaw,tri,square,expo,rsh,qrsh};
// --- for LFOs - MODE
enum {sync,shot,free};
UINT m_uLFOMode; // to store MODE
// --- MIDI note that is being played
UINT m_uMIDINoteNumber;
protected:
// --- PROTECTED: generally these are either basic calc variables
// and modulation stuff
// --- calculation variables
double m_dSampleRate; // fs
double m_dFo; // current (actual) frequency of oscillator
double m_dPulseWidth; // pulse width in % for calculation
// --- for noise and random sample/hold
UINT m_uPNRegister; // for PN Noise sequence
int m_nRSHCounter; // random sample/hold counter
double m_dRSHValue; // currnet rsh output
// --- for DPW
double m_dDPWSquareModulator; // square toggle
double m_dDPW_z1; // memory register for differentiator
// --- mondulation inputs
double m_dFoMod; /* modulation input -1 to +1 */
double m_dPitchBendMod; /* modulation input -1 to +1 */
double m_dFoModLin; /* FM modulation input -1 to +1 (not actually used in Yamaha FM!) */
double m_dPhaseMod; /* Phase modulation input -1 to +1 (used for DX synth) */
double m_dPWMod; /* modulation input for PWM -1 to +1 */
double m_dAmpMod; /* output amplitude modulation for AM 0 to +1 (not dB)*/
public:
// --- FUNCTIONS: all public
//
// --- modulo functions for master/slave operation
// --- increment the modulo counters
inline void incModulo(){m_dModulo += m_dInc;}
// --- check and wrap the modulo
// returns true if modulo wrapped
inline bool checkWrapModulo()
{
// --- for positive frequencies
if(m_dInc > 0 && m_dModulo >= 1.0)
{
m_dModulo -= 1.0;
return true;
}
// --- for negative frequencies
if(m_dInc < 0 && m_dModulo <= 0.0)
{
m_dModulo += 1.0;
return true;
}
return false;
}
// --- reset the modulo (required for master->slave operations)
inline void resetModulo(double d = 0.0){m_dModulo = d;}
// --- modulation functions - NOT needed/used if you implement the Modulation Matrix!
//
// --- output amplitude modulation (AM, not tremolo (dB); 0->1, NOT dB
inline void setAmplitudeMod(double dAmp){m_dAmpMod = dAmp;}
// --- modulation, exponential
inline void setFoModExp(double dMod){m_dFoMod = dMod;}
inline void setPitchBendMod(double dMod){m_dPitchBendMod = dMod;}
// --- for FM only (not used in Yamaha or my DX synths!)
inline void setFoModLin(double dMod){m_dFoModLin = dMod;}
// --- for Yamaha and my DX Synth
inline void setPhaseMod(double dMod){m_dPhaseMod = dMod;}
// --- PWM for square waves only
inline void setPWMod(double dMod){m_dPWMod = dMod;}
// --- VIRTUAL FUNCTIONS ----------------------------------------- //
//
// --- PURE ABSTRACT: derived class MUST implement
// --- start/stop control
virtual void startOscillator() = 0;
virtual void stopOscillator() = 0;
// --- render a sample
// for LFO: pAuxOutput = QuadPhaseOutput
// Pitched: pAuxOutput = Right channel (return value is left Channel
virtual double doOscillate(double* pAuxOutput = NULL) = 0;
// --- ABSTRACT: derived class overrides if needed
virtual void setSampleRate(double dFs){m_dSampleRate = dFs;}
// --- reset counters, etc...
virtual void reset();
// INLINE FUNCTIONS: these are inlined because they will be
// called every sample period
// You may want to move them to the .cpp file and
// enable the compiler Optimization setting for
// Inline Function Expansion: Any Suitable though
// inlining here forces it.
//
// --- update the frequency, amp mod and PWM
inline virtual void update()
{
// --- ignore LFO mode for noise sources
if(m_uWaveform == rsh || m_uWaveform == qrsh)
m_uLFOMode = free;
// --- do the complete frequency mod
m_dFo = m_dOscFo*m_dFoRatio*pitchShiftMultiplier(m_dFoMod +
m_dPitchBendMod +
m_nOctave*12.0 +
m_nSemitones +
m_nCents/100.0);
// --- apply linear FM (not used in book projects)
m_dFo += m_dFoModLin;
// --- bound Fo (can go outside for FM/PM mod)
// +/- 20480 for FM/PM
if(m_dFo > OSC_FO_MAX)
m_dFo = OSC_FO_MAX;
if(m_dFo < -OSC_FO_MAX)
m_dFo = -OSC_FO_MAX;
// --- calculate increment (a.k.a. phase a.k.a. phaseIncrement, etc...)
m_dInc = m_dFo/m_dSampleRate;
// --- Pulse Width Modulation --- //
// --- limits are 2% and 98%
m_dPulseWidth = m_dPulseWidthControl + m_dPWMod*(OSC_PULSEWIDTH_MAX - OSC_PULSEWIDTH_MIN)/OSC_PULSEWIDTH_MIN;
// --- bound the PWM to the range
m_dPulseWidth = fmin(m_dPulseWidth, OSC_PULSEWIDTH_MAX);
m_dPulseWidth = fmax(m_dPulseWidth, OSC_PULSEWIDTH_MIN);
}
};