1 // synthv1_wave.h
2 //
3 /****************************************************************************
4    Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved.
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License
8    as published by the Free Software Foundation; either version 2
9    of the License, or (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, write to the Free Software Foundation, Inc.,
18    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 
20 *****************************************************************************/
21 
22 #ifndef __synthv1_wave_h
23 #define __synthv1_wave_h
24 
25 #include <cstdint>
26 
27 
28 // forward decls.
29 class synthv1_wave_sched;
30 
31 
32 //-------------------------------------------------------------------------
33 // synthv1_wave - smoothed (integrating oversampled) wave table.
34 //
35 
36 class synthv1_wave
37 {
38 public:
39 
40 	// shape.
41 	enum Shape { Pulse = 0, Saw, Sine, Rand, Noise };
42 
43 	// ctor.
44 	synthv1_wave(uint32_t nsize = 4096, uint16_t nover = 24, uint16_t ntabs = 8);
45 
46 	// dtor.
47 	~synthv1_wave();
48 
49 	// properties.
shape()50 	Shape shape() const
51 		{ return m_shape; }
width()52 	float width() const
53 		{ return m_width; }
bandl()54 	bool bandl() const
55 		{ return m_bandl; }
56 
57 	// sample rate.
setSampleRate(float srate)58 	void setSampleRate(float srate)
59 		{ m_srate = srate; }
sampleRate()60 	float sampleRate() const
61 		{ return m_srate; }
62 
63 	// table size (in frames)
size()64 	uint32_t size() const
65 		{ return m_nsize; }
66 
67 	// phase-zero (for slave reset)
phase0()68 	float phase0() const
69 		{ return m_phase0; }
70 
71 	// init.
72 	void reset(Shape shape, float width, bool bandl = false);
73 	// init.sync.
74 	void reset_sync();
75 
76 	// init.test
77 	void reset_test(Shape shape, float width, bool bandl = false)
78 	{
79 		if (shape != m_shape || width != m_width
80 			|| (m_ntabs > 0 && bandl != m_bandl))
81 			reset(shape, width, bandl);
82 	}
83 
84 	// phasor.
85 	struct Phase
86 	{
PhasePhase87 		Phase() { reset(); }
88 
89 		float    phase;
90 		float    ftab;
91 		uint16_t itab;
92 
93 		Phase   *slave;
94 		float    slave_phase0;
95 
resetPhase96 		void reset()
97 		{
98 			phase = ftab = slave_phase0 = 0.0f;
99 			itab  = 0;
100 			slave = 0;
101 		}
102 	};
103 
104 	// begin.
105 	float start(Phase& phase, float pshift = 0.0f, float freq = 0.0f) const
106 	{
107 		update(phase, freq);
108 
109 		phase.phase = m_phase0 + pshift;
110 		if (phase.phase >= 1.0f)
111 			phase.phase -= 1.0f;
112 
113 		return sample(phase, freq);
114 	}
115 
116 	// iterate.
sample(Phase & phase,float freq)117 	float sample(Phase& phase, float freq) const
118 	{
119 		const float index = phase.phase * float(m_nsize);
120 		const uint32_t i = uint32_t(index);
121 		const float alpha = index - float(i);
122 
123 		phase.phase += freq / m_srate;
124 		if (phase.phase >= 1.0f) {
125 			phase.phase -= 1.0f;
126 			if (phase.slave)
127 				phase.slave->phase = phase.slave_phase0;
128 		}
129 
130 		if (phase.itab < m_ntabs) {
131 			const float x0 = interp(i, phase.itab, alpha);
132 			const float x1 = interp(i, phase.itab + 1, alpha);
133 			return x0 + phase.ftab * (x1 - x0);
134 		} else {
135 			return interp(i, phase.itab, alpha);
136 		}
137 	}
138 
139 	// interpolate.
interp(uint32_t i,uint16_t itab,float alpha)140 	float interp(uint32_t i, uint16_t itab, float alpha) const
141 	{
142 		float *frames = m_tables[itab];
143 
144 		const float x0 = frames[i];
145 		const float x1 = frames[i + 1];
146 #if 0	// cubic interp.
147 		const float x2 = frames[i + 2];
148 		const float x3 = frames[i + 3];
149 
150 		const float c1 = (x2 - x0) * 0.5f;
151 		const float b1 = (x1 - x2);
152 		const float b2 = (c1 + b1);
153 		const float c3 = (x3 - x1) * 0.5f + b2 + b1;
154 		const float c2 = (c3 + b2);
155 
156 		return (((c3 * alpha) - c2) * alpha + c1) * alpha + x1;
157 #else	// linear interp.
158 		return x0 + alpha * (x1 - x0);
159 #endif
160 	}
161 
162 	// absolute value.
value(float phase)163 	float value(float phase) const
164 	{
165 		phase += m_phase0;
166 		if (phase >= 1.0f)
167 			phase -= 1.0f;
168 
169 		return m_tables[m_ntabs][uint32_t(phase * float(m_nsize))];
170 	}
171 
172 	// post-iter.
update(Phase & phase,float freq)173 	void update(Phase& phase, float freq) const
174 	{
175 		if (freq < m_min_freq) {
176 			phase.itab  = m_ntabs;
177 			phase.ftab  = 0.0f;
178 		} else if (freq < m_max_freq) {
179 			phase.ftab  = fast_log2f(m_max_freq / freq);
180 			phase.itab  = uint16_t(phase.ftab);
181 			phase.ftab -= float(phase.itab);
182 		} else {
183 			phase.itab  = 0;
184 			phase.ftab  = 0.0f;
185 		}
186 	}
187 
188 protected:
189 
190 	// fast log2f approximation.
fast_log2f(float x)191 	static inline float fast_log2f ( float x )
192 	{
193 		union { float f; uint32_t i; } u;
194 		u.f = x;
195 		return (u.i * 1.192092896e-7f) - 126.943612f;
196 	}
197 
198 	// init pulse tables.
199 	void reset_pulse();
200 	// init pulse partial table.
201 	void reset_pulse_part(uint16_t itab);
202 
203 	// init saw tables.
204 	void reset_saw();
205 	// init saw partial table.
206 	void reset_saw_part(uint16_t itab);
207 
208 	// init sine tables.
209 	void reset_sine();
210 	// init sine partial table.
211 	void reset_sine_part(uint16_t itab);
212 
213 	// init random tables.
214 	void reset_rand();
215 	// init random partial table.
216 	void reset_rand_part(uint16_t itab);
217 
218 	// init noise tables.
219 	void reset_noise();
220 	// init noise partial table.
221 	void reset_noise_part(uint16_t itab);
222 
223 	// post-processors.
224 	void reset_filter(uint16_t itab);
225 	void reset_normalize(uint16_t itab);
226 	void reset_interp(uint16_t itab);
227 
228 	// Hal Chamberlain's pseudo-random linear congruential method.
pseudo_srand()229 	uint32_t pseudo_srand ()
230 		{ return (m_srand = (m_srand * 196314165) + 907633515); }
pseudo_randf()231 	float pseudo_randf ()
232 		{ return pseudo_srand() / float(0x8000U << 16) - 1.0f; }
233 
234 private:
235 
236 	uint32_t m_nsize;
237 	uint16_t m_nover;
238 	uint16_t m_ntabs;
239 
240 	Shape    m_shape;
241 	float    m_width;
242 	bool     m_bandl;
243 
244 	float    m_srate;
245 	float  **m_tables;
246 	float    m_phase0;
247 
248 	uint32_t m_srand;
249 
250 	float    m_min_freq;
251 	float    m_max_freq;
252 
253 	synthv1_wave_sched *m_sched;
254 };
255 
256 
257 //-------------------------------------------------------------------------
258 // synthv1_wave_lf - hard/non-smoothed wave table (eg. LFO).
259 //
260 
261 class synthv1_wave_lf : public synthv1_wave
262 {
263 public:
264 
265 	// ctor.
266 	synthv1_wave_lf(uint32_t nsize = 1024)
267 		: synthv1_wave(nsize, 0, 0) {}
268 };
269 
270 
271 //-------------------------------------------------------------------------
272 // synthv1_oscillator - wave table oscillator
273 //
274 
275 class synthv1_oscillator
276 {
277 public:
278 
279 	// ctor.
280 	synthv1_oscillator(synthv1_wave *wave = 0) { reset(wave); }
281 
282 	// wave and phase accessors.
reset(synthv1_wave * wave)283 	void reset(synthv1_wave *wave)
284 		{ m_wave = wave; m_phase.reset(); }
285 
wave()286 	synthv1_wave *wave() const
287 		{ return m_wave; }
288 
289 	// begin.
290 	float start(float pshift = 0.0f, float freq = 0.0f)
291 		{ return m_wave->start(m_phase, pshift, freq); }
292 
293 	// iterate.
sample(float freq)294 	float sample(float freq)
295 		{ return m_wave->sample(m_phase, freq); }
296 
297 	// post-iter.
update(float freq)298 	void update(float freq)
299 		{ m_wave->update(m_phase, freq); }
300 
301 	// hard-sync slave.
sync(synthv1_oscillator * slave)302 	void sync(synthv1_oscillator *slave)
303 	{
304 		if (slave && slave->m_wave) {
305 			m_phase.slave = &(slave->m_phase);
306 			m_phase.slave_phase0 = (slave->m_wave)->phase0();
307 		} else {
308 			m_phase.slave = 0;
309 			m_phase.slave_phase0 = 0.0f;
310 		}
311 	}
312 
313 	// phase-shift accessor.
pshift()314 	float pshift() const
315 	{
316 		const float pshift = m_wave->phase0() + m_phase.phase;
317 		return (pshift >= 1.0f ? pshift - 1.0f : pshift);
318 	}
319 
320 private:
321 
322 	synthv1_wave       *m_wave;
323 	synthv1_wave::Phase m_phase;
324 };
325 
326 
327 #endif	// __synthv1_wave_h
328 
329 // end of synthv1_wave.h
330