1 // samplv1_sample.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 __samplv1_sample_h
23 #define __samplv1_sample_h
24 
25 #include <cstdint>
26 
27 #include <cstdlib>
28 #include <cstring>
29 
30 #include <cmath>
31 
32 
33 // forward decls.
34 class samplv1;
35 
36 
37 //-------------------------------------------------------------------------
38 // samplv1_sample - sampler wave table.
39 //
40 
41 class samplv1_sample
42 {
43 public:
44 
45 	// ctor.
46 	samplv1_sample(float srate = 44100.0f);
47 
48 	// dtor.
49 	~samplv1_sample();
50 
51 	// nominal sample-rate.
setSampleRate(float srate)52 	void setSampleRate(float srate)
53 		{ m_srate = srate; }
sampleRate()54 	float sampleRate() const
55 		{ return m_srate; }
56 
57 	// reverse mode.
setReverse(bool reverse)58 	void setReverse(bool reverse)
59 	{
60 		if (( m_reverse && !reverse) ||
61 			(!m_reverse &&  reverse)) {
62 			m_reverse = reverse;
63 			reverse_sync();
64 		}
65 	}
66 
isReverse()67 	bool isReverse() const
68 		{ return m_reverse; }
69 
70 	// offset mode.
setOffset(bool offset)71 	void setOffset(bool offset)
72 	{
73 		m_offset = offset;
74 
75 		updateOffset();
76 	}
77 
isOffset()78 	bool isOffset() const
79 		{ return m_offset; }
80 
81 	// offset range.
82 	void setOffsetRange(uint32_t start, uint32_t end);
83 
offsetStart()84 	uint32_t offsetStart() const
85 		{ return m_offset_start; }
offsetEnd()86 	uint32_t offsetEnd() const
87 		{ return m_offset_end; }
88 
offsetPhase0(uint16_t itab)89 	float offsetPhase0(uint16_t itab) const
90 		{ return (m_offset && m_offset_phase0 ? m_offset_phase0[itab] : 0.0f); }
91 
92 	// loop mode.
setLoop(bool loop)93 	void setLoop(bool loop)
94 	{
95 		m_loop = loop;
96 
97 		updateLoop();
98 	}
99 
isLoop()100 	bool isLoop() const
101 		{ return m_loop; }
102 
103 	// loop range.
104 	void setLoopRange(uint32_t start, uint32_t end);
105 
loopStart()106 	uint32_t loopStart() const
107 		{ return m_loop_start; }
loopEnd()108 	uint32_t loopEnd() const
109 		{ return m_loop_end; }
110 
loopPhase1(uint16_t itab)111 	float loopPhase1(uint16_t itab) const
112 		{ return (m_loop_phase1 ? m_loop_phase1[itab] : 0.0f); }
loopPhase2(uint16_t itab)113 	float loopPhase2(uint16_t itab) const
114 		{ return (m_loop_phase2 ? m_loop_phase2[itab] : 0.0f); }
115 
116 	// loop cross-fade (in number of frames)
setLoopCrossFade(uint32_t xfade)117 	void setLoopCrossFade(uint32_t xfade)
118 		{ m_loop_xfade = xfade; }
loopCrossFade()119 	uint32_t loopCrossFade() const
120 		{ return m_loop_xfade; }
121 
122 	// loop zero-crossing detection
setLoopZeroCrossing(bool xzero)123 	void setLoopZeroCrossing(bool xzero)
124 		{ m_loop_xzero = xzero; }
isLoopZeroCrossing()125 	bool isLoopZeroCrossing() const
126 		{ return m_loop_xzero; }
127 
128 	// init.
129 	bool open(const char *filename, float freq0 = 1.0f, uint16_t otabs = 0);
130 	void close();
131 
132 	// accessors.
filename()133 	const char *filename() const
134 		{ return m_filename; }
channels()135 	uint16_t channels() const
136 		{ return m_nchannels; }
rate()137 	float rate() const
138 		{ return m_rate0; }
freq()139 	float freq() const
140 		{ return m_freq0; }
length()141 	uint32_t length() const
142 		{ return m_nframes; }
143 
144 	// resampler ratio
ratio()145 	float ratio() const
146 		{ return m_ratio; }
147 
148 	// reset.
reset(float freq0)149 	void reset(float freq0)
150 	{
151 		m_freq0 = freq0;
152 		m_ratio = m_rate0 / (m_freq0 * m_srate);
153 	}
154 
155 	// sample table index.
itab(float freq)156 	uint16_t itab(float freq) const
157 	{
158 		int ret = int(m_ntabs >> 1) + fast_ilog2f(freq / m_freq0);
159 
160 		if (ret < 0)
161 			ret = 0;
162 		else
163 		if (ret > m_ntabs)
164 			ret = m_ntabs;
165 
166 		return ret;
167 	}
168 
169 	// sample table ratio.
ftab(uint16_t itab)170 	float ftab(uint16_t itab) const
171 	{
172 		float ret = 1.0f;
173 		const uint16_t itab0 = (m_ntabs >> 1);
174 		if (itab < itab0)
175 			ret *= float((itab0 - itab) << 1);
176 		else
177 		if (itab > itab0)
178 			ret /= float((itab - itab0) << 1);
179 		return ret;
180 	}
181 
182 	// number of pitch-shifted octaves.
otabs()183 	uint16_t otabs() const
184 		{ return m_ntabs >> 1; }
185 
186 	// frame value.
frames(uint16_t itab,uint16_t k)187 	float *frames(uint16_t itab, uint16_t k) const
188 		{ return m_pframes[itab][k]; }
frames(uint16_t k)189 	float *frames(uint16_t k) const
190 		{ return frames(m_ntabs >> 1, k); }
191 
192 	// predicate.
isOver(uint32_t index)193 	bool isOver(uint32_t index) const
194 		{ return !m_pframes || (index >= m_offset_end2); }
195 
196 protected:
197 
198 	// reverse sample buffer.
199 	void reverse_sync();
200 
201 	// zero-crossing aliasing .
202 	uint32_t zero_crossing(uint16_t itab, uint32_t i, int *slope = nullptr) const;
203 	float zero_crossing_k(uint16_t itab, uint32_t i) const;
204 
205 	// offset/loop update.
206 	void updateOffset();
207 	void updateLoop();
208 
209 	// fast log10(x)/log10(2) approximation.
fast_ilog2f(float x)210 	static inline int fast_ilog2f ( float x )
211 	{
212 		union { float f; int32_t i; } u; u.f = x;
213 		return (((u.i & 0x7f800000) >> 23) - 0x7f)
214 			+ (u.i & 0x007fffff) / float(0x800000);
215 	}
216 
217 private:
218 
219 	// instance variables.
220 	float    m_srate;
221 	uint16_t m_ntabs;
222 
223 	char    *m_filename;
224 	uint16_t m_nchannels;
225 	float    m_rate0;
226 	float    m_freq0;
227 	float    m_ratio;
228 
229 	uint32_t m_nframes;
230 	float ***m_pframes;
231 	bool     m_reverse;
232 
233 	bool     m_offset;
234 	uint32_t m_offset_start;
235 	uint32_t m_offset_end;
236 	float   *m_offset_phase0;
237 	uint32_t m_offset_end2;
238 
239 	bool     m_loop;
240 	uint32_t m_loop_start;
241 	uint32_t m_loop_end;
242 	float   *m_loop_phase1;
243 	float   *m_loop_phase2;
244 	uint32_t m_loop_xfade;
245 	bool     m_loop_xzero;
246 };
247 
248 
249 //-------------------------------------------------------------------------
250 // samplv1_generator - sampler oscillator (sort of:)
251 
252 class samplv1_generator
253 {
254 public:
255 
256 	// ctor.
257 	samplv1_generator(samplv1_sample *sample = nullptr) { reset(sample); }
258 
259 	// sample accessor.
sample()260 	samplv1_sample *sample() const
261 		{ return m_sample; }
262 
263 	// reset.
reset(samplv1_sample * sample)264 	void reset(samplv1_sample *sample)
265 	{
266 		m_sample = sample;
267 
268 		start(m_sample ? m_sample->freq() : 1.0f);
269 	}
270 
271 	// reset loop.
setLoop(bool loop)272 	void setLoop(bool loop)
273 	{
274 		m_loop = loop;
275 
276 		if (m_loop && m_sample) {
277 			m_loop_phase1 = m_sample->loopPhase1(m_itab);
278 			m_loop_phase2 = m_sample->loopPhase2(m_itab);
279 		} else {
280 			m_loop_phase1 = 0.0f;
281 			m_loop_phase2 = 0.0f;
282 		}
283 	}
284 
285 	// begin.
start(float freq)286 	void start(float freq)
287 	{
288 		m_itab   = (m_sample ? m_sample->itab(freq) : 0);
289 		m_ftab   = (m_sample ? m_sample->ftab(m_itab) : 1.0f);
290 
291 		m_phase0 = (m_sample ? m_sample->offsetPhase0(m_itab) : 0.0f);
292 		m_phase  = m_phase0;
293 		m_index  = 0;
294 		m_alpha  = 0.0f;
295 
296 		m_phase1 = 0.0f;
297 		m_index1 = 0;
298 		m_alpha1 = 0.0f;
299 		m_xgain1 = 1.0f;
300 
301 		setLoop(m_sample ? m_sample->isLoop() : false);
302 	}
303 
304 	// iterate.
next(float freq)305 	void next(float freq)
306 	{
307 		const float ratio = (m_sample ? m_sample->ratio() : 1.0f);
308 		const float delta = freq * ratio * m_ftab;
309 
310 		m_index  = uint32_t(m_phase);
311 		m_alpha  = m_phase - float(m_index);
312 		m_phase += delta;
313 
314 		if (m_loop && m_sample) {
315 			const uint32_t xfade = m_sample->loopCrossFade(); // nframes.
316 			if (xfade > 0) {
317 				const float xfade1 = float(xfade); // nframes.
318 				if (m_phase >= m_loop_phase2 - xfade1) {
319 					if (//m_sample->isOver(m_index) ||
320 						m_phase >= m_loop_phase2) {
321 						m_phase -= m_loop_phase1 * ::ceilf(delta / m_loop_phase1);
322 						if (m_phase < m_phase0)
323 							m_phase = m_phase0;
324 					}
325 					if (m_phase1 > 0.0f) {
326 						m_index1 = int(m_phase1);
327 						m_alpha1 = m_phase1 - float(m_index1);
328 						m_phase1 += delta;
329 						m_xgain1 -= delta / xfade1;
330 						if (m_xgain1 < 0.0f)
331 							m_xgain1 = 0.0f;
332 					} else {
333 						m_phase1 = m_phase - m_loop_phase1;
334 						if (m_phase1 < m_phase0)
335 							m_phase1 = m_phase0;
336 						m_xgain1 = 1.0f;
337 					}
338 				}
339 				else
340 				if (m_phase1 > 0.0f) {
341 					m_phase1 = 0.0f;
342 					m_index1 = 0;
343 					m_alpha1 = 0.0f;
344 					m_xgain1 = 1.0f;
345 				}
346 			}
347 			else
348 			if (m_phase >= m_loop_phase2) {
349 				m_phase -= m_loop_phase1 * ::ceilf(delta / m_loop_phase1);
350 				if (m_phase < m_phase0)
351 					m_phase = m_phase0;
352 			}
353 		}
354 	}
355 
356 	// sample.
value(uint16_t k)357 	float value(uint16_t k) const
358 	{
359 		if (isOver())
360 			return 0.0f;
361 
362 		float ret = m_xgain1 * interp(k, m_index, m_alpha);
363 		if (m_index1 > 0)
364 			ret += (1.0f - m_xgain1) * interp(k, m_index1, m_alpha1);
365 
366 		return ret;
367 	}
368 
369 	// predicate.
isOver()370 	bool isOver() const
371 		{ return !m_loop && (m_sample ? m_sample->isOver(m_index) : true); }
372 
373 protected:
374 
375 	// sample (cubic interpolate).
interp(uint16_t k,uint32_t index,float alpha)376 	float interp(uint16_t k, uint32_t index, float alpha) const
377 	{
378 		const float *frames = m_sample->frames(m_itab, k);
379 
380 		const float x0 = frames[index];
381 		const float x1 = frames[index + 1];
382 		const float x2 = frames[index + 2];
383 		const float x3 = frames[index + 3];
384 
385 		const float c1 = (x2 - x0) * 0.5f;
386 		const float b1 = (x1 - x2);
387 		const float b2 = (c1 + b1);
388 		const float c3 = (x3 - x1) * 0.5f + b2 + b1;
389 		const float c2 = (c3 + b2);
390 
391 		return (((c3 * alpha) - c2) * alpha + c1) * alpha + x1;
392 	}
393 
394 private:
395 
396 	// iterator variables.
397 	samplv1_sample *m_sample;
398 
399 	uint16_t m_itab;
400 	float    m_ftab;
401 
402 	float    m_phase0;
403 	float    m_phase;
404 	uint32_t m_index;
405 	float    m_alpha;
406 
407 	bool     m_loop;
408 	float    m_loop_phase1;
409 	float    m_loop_phase2;
410 
411 	float    m_phase1;
412 	uint32_t m_index1;
413 	float    m_alpha1;
414 	float    m_xgain1;
415 };
416 
417 
418 #endif	// __samplv1_sample_h
419 
420 // end of samplv1_sample.h
421