1 /* Calf DSP Library
2 * DSP primitives.
3 *
4 * Copyright (C) 2001-2007 Krzysztof Foltman
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02111-1307, USA.
20 */
21 #ifndef __CALF_PRIMITIVES_H
22 #define __CALF_PRIMITIVES_H
23
24 #include <assert.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <cmath>
29 #include <cstdlib>
30 #include <map>
31 #include <algorithm>
32
33 namespace dsp {
34
35 /// Set a float to zero
zero(float & v)36 inline void zero(float &v) {
37 v = 0.f;
38 };
39
40 /// Set a double to zero
zero(double & v)41 inline void zero(double &v) {
42 v = 0.0;
43 };
44
45 /// Set 64-bit unsigned integer value to zero
zero(uint64_t & v)46 inline void zero(uint64_t &v) { v = 0; };
47 /// Set 32-bit unsigned integer value to zero
zero(uint32_t & v)48 inline void zero(uint32_t &v) { v = 0; };
49 /// Set 16-bit unsigned integer value to zero
zero(uint16_t & v)50 inline void zero(uint16_t &v) { v = 0; };
51 /// Set 8-bit unsigned integer value to zero
zero(uint8_t & v)52 inline void zero(uint8_t &v) { v = 0; };
53 /// Set 64-bit signed integer value to zero
zero(int64_t & v)54 inline void zero(int64_t &v) { v = 0; };
55 /// Set 32-bit signed integer value to zero
zero(int32_t & v)56 inline void zero(int32_t &v) { v = 0; };
57 /// Set 16-bit signed integer value to zero
zero(int16_t & v)58 inline void zero(int16_t &v) { v = 0; };
59 /// Set 8-bit signed integer value to zero
zero(int8_t & v)60 inline void zero(int8_t &v) { v = 0; };
61
62 /// Set array (buffer or anything similar) to vector of zeroes
63 template<class T>
zero(T * data,unsigned int size)64 void zero(T *data, unsigned int size) {
65 T value;
66 dsp::zero(value);
67 for (unsigned int i=0; i<size; i++)
68 *data++ = value;
69 }
70
71 /// Set array (buffer or anything similar) to vector of values
72 template<class T>
fill(T * data,T value,unsigned int size)73 void fill(T *data, T value, unsigned int size) {
74 for (unsigned int i=0; i<size; i++)
75 *data++ = value;
76 }
77
78 template<class T = float>struct stereo_sample {
79 T left;
80 T right;
81 /// default constructor - preserves T's semantics (ie. no implicit initialization to 0)
stereo_samplestereo_sample82 inline stereo_sample() {
83 }
stereo_samplestereo_sample84 inline stereo_sample(T _left, T _right) {
85 left = _left;
86 right = _right;
87 }
stereo_samplestereo_sample88 inline stereo_sample(T _both) {
89 left = right = _both;
90 }
91 template<typename U>
stereo_samplestereo_sample92 inline stereo_sample(const stereo_sample<U> &value) {
93 left = value.left;
94 right = value.right;
95 }
96 inline stereo_sample& operator=(const T &value) {
97 left = right = value;
98 return *this;
99 }
100 template<typename U>
101 inline stereo_sample& operator=(const stereo_sample<U> &value) {
102 left = value.left;
103 right = value.right;
104 return *this;
105 }
106 /*
107 inline operator T() const {
108 return (left+right)/2;
109 }
110 */
111 inline stereo_sample& operator*=(const T &multiplier) {
112 left *= multiplier;
113 right *= multiplier;
114 return *this;
115 }
116 inline stereo_sample& operator+=(const stereo_sample<T> &value) {
117 left += value.left;
118 right += value.right;
119 return *this;
120 }
121 inline stereo_sample& operator-=(const stereo_sample<T> &value) {
122 left -= value.left;
123 right -= value.right;
124 return *this;
125 }
126 template<typename U> inline stereo_sample<U> operator*(const U &value) const {
127 return stereo_sample<U>(left*value, right*value);
128 }
129 /*inline stereo_sample<float> operator*(float value) const {
130 return stereo_sample<float>(left*value, right*value);
131 }
132 inline stereo_sample<double> operator*(double value) const {
133 return stereo_sample<double>(left*value, right*value);
134 }*/
135 inline stereo_sample<T> operator+(const stereo_sample<T> &value) {
136 return stereo_sample(left+value.left, right+value.right);
137 }
138 inline stereo_sample<T> operator-(const stereo_sample<T> &value) {
139 return stereo_sample(left-value.left, right-value.right);
140 }
141 inline stereo_sample<T> operator+(const T &value) {
142 return stereo_sample(left+value, right+value);
143 }
144 inline stereo_sample<T> operator-(const T &value) {
145 return stereo_sample(left-value, right-value);
146 }
147 inline stereo_sample<float> operator+(float value) {
148 return stereo_sample<float>(left+value, right+value);
149 }
150 inline stereo_sample<float> operator-(float value) {
151 return stereo_sample<float>(left-value, right-value);
152 }
153 inline stereo_sample<double> operator+(double value) {
154 return stereo_sample<double>(left+value, right+value);
155 }
156 inline stereo_sample<double> operator-(double value) {
157 return stereo_sample<double>(left-value, right-value);
158 }
159 };
160
161 /// Multiply constant by stereo_value
162 template<class T>
163 inline stereo_sample<T> operator*(const T &value, const stereo_sample<T> &value2) {
164 return stereo_sample<T>(value2.left*value, value2.right*value);
165 }
166
167 /// Add constant to stereo_value
168 template<class T>
169 inline stereo_sample<T> operator+(const T &value, const stereo_sample<T> &value2) {
170 return stereo_sample<T>(value2.left+value, value2.right+value);
171 }
172
173 /// Subtract stereo_value from constant (yields stereo_value of course)
174 template<class T>
175 inline stereo_sample<T> operator-(const T &value, const stereo_sample<T> &value2) {
176 return stereo_sample<T>(value-value2.left, value-value2.right);
177 }
178
179 /// Shift value right by 'bits' bits (multiply by 2^-bits)
180 template<typename T>
181 inline stereo_sample<T> shr(stereo_sample<T> v, int bits = 1) {
182 v.left = shr(v.left, bits);
183 v.right = shr(v.right, bits);
184 return v;
185 }
186
187 /// Set a stereo_sample<T> value to zero
188 template<typename T>
zero(stereo_sample<T> & v)189 inline void zero(stereo_sample<T> &v) {
190 dsp::zero(v.left);
191 dsp::zero(v.right);
192 }
193
194 /// 'Small value' for integer and other types
195 template<typename T>
small_value()196 inline T small_value() {
197 return 0;
198 }
199
200 /// 'Small value' for floats (2^-24) - used for primitive underrun prevention. The value is pretty much arbitrary (allowing for 24-bit signals normalized to 1.0).
201 template<>
202 inline float small_value<float>() {
203 return (1.0/16777216.0); // allows for 2^-24, should be enough for 24-bit DACs at least :)
204 }
205
206 /// 'Small value' for doubles (2^-24) - used for primitive underrun prevention. The value is pretty much arbitrary.
207 template<>
208 inline double small_value<double>() {
209 return (1.0/16777216.0);
210 }
211
212 /// Convert a single value to single value = do nothing :) (but it's a generic with specialisation for stereo_sample)
213 template<typename T>
mono(T v)214 inline float mono(T v) {
215 return v;
216 }
217
218 /// Convert a stereo_sample to single value by averaging two channels
219 template<typename T>
mono(stereo_sample<T> v)220 inline T mono(stereo_sample<T> v) {
221 return shr(v.left+v.right);
222 }
223
224 /// Clip a value to [min, max]
225 template<typename T>
clip(T value,T min,T max)226 inline T clip(T value, T min, T max) {
227 if (value < min) return min;
228 if (value > max) return max;
229 return value;
230 }
231
232 /// Clip a double to [-1.0, +1.0]
clip11(double value)233 inline double clip11(double value) {
234 double a = fabs(value);
235 if (a<=1) return value;
236 return (value<0) ? -1.0 : 1.0;
237 }
238
239 /// Clip a float to [-1.0f, +1.0f]
clip11(float value)240 inline float clip11(float value) {
241 float a = fabsf(value);
242 if (a<=1) return value;
243 return (value<0) ? -1.0f : 1.0f;
244 }
245
246 /// Clip a double to [0.0, +1.0]
clip01(double value)247 inline double clip01(double value) {
248 double a = fabs(value-0.5);
249 if (a<=0.5) return value;
250 return (a<0) ? -0.0 : 1.0;
251 }
252
253 /// Clip a float to [0.0f, +1.0f]
clip01(float value)254 inline float clip01(float value) {
255 float a = fabsf(value-0.5f);
256 if (a<=0.5f) return value;
257 return (value < 0) ? -0.0f : 1.0f;
258 }
259
260 // Linear interpolation (mix-way between v1 and v2).
261 template<typename T, typename U>
lerp(T v1,T v2,U mix)262 inline T lerp(T v1, T v2, U mix) {
263 return v1+(v2-v1)*mix;
264 }
265
266 // Linear interpolation for stereo values (mix-way between v1 and v2).
267 template<typename T>
lerp(stereo_sample<T> & v1,stereo_sample<T> & v2,float mix)268 inline stereo_sample<T> lerp(stereo_sample<T> &v1, stereo_sample<T> &v2, float mix) {
269 return stereo_sample<T>(v1.left+(v2.left-v1.left)*mix, v1.right+(v2.right-v1.right)*mix);
270 }
271
272 /**
273 * decay-only envelope (linear or exponential); deactivates itself when it goes below a set point (epsilon)
274 */
275 class decay
276 {
277 double value, initial;
278 unsigned int age, mask;
279 bool active;
280 public:
decay()281 decay() {
282 active = false;
283 mask = 127;
284 initial = value = 0.0;
285 }
get_active()286 inline bool get_active() {
287 return active;
288 }
get()289 inline double get() {
290 return active ? value : 0.0;
291 }
set(double v)292 inline void set(double v) {
293 initial = value = v;
294 active = true;
295 age = 0;
296 }
297 /// reinitialise envelope (must be called if shape changes from linear to exponential or vice versa in the middle of envelope)
reinit()298 inline void reinit()
299 {
300 initial = value;
301 age = 1;
302 }
add(double v)303 inline void add(double v) {
304 if (active)
305 value += v;
306 else
307 value = v;
308 initial = value;
309 age = 0;
310 active = true;
311 }
calc_exp_constant(double times,double cycles)312 static inline double calc_exp_constant(double times, double cycles)
313 {
314 if (cycles < 1.0)
315 cycles = 1.0;
316 return pow(times, 1.0 / cycles);
317 }
age_exp(double constant,double epsilon)318 inline void age_exp(double constant, double epsilon) {
319 if (active) {
320 if (!(age & mask))
321 value = initial * pow(constant, (double)age);
322 else
323 value *= constant;
324 if (value < epsilon)
325 active = false;
326 age++;
327 }
328 }
age_lin(double constant,double epsilon)329 inline void age_lin(double constant, double epsilon) {
330 if (active) {
331 if (!(age & mask))
332 value = initial - constant * age;
333 else
334 value -= constant;
335 if (value < epsilon)
336 active = false;
337 age++;
338 }
339 }
deactivate()340 inline void deactivate() {
341 active = false;
342 value = 0;
343 }
344 };
345
346 /**
347 * Force "small enough" float value to zero
348 */
sanitize(float & value)349 inline void sanitize(float &value)
350 {
351 // real number?
352 if (std::abs(value) < small_value<float>())
353 value = 0.f;
354 // close to 0?
355 const int val = *reinterpret_cast <const int *> (&value);
356 if ((val & 0x7F800000) == 0 && (val & 0x007FFFFF) != 0)
357 value = 0.f;
358 }
_sanitize(float value)359 inline float _sanitize(float value)
360 {
361 if (std::abs(value) < small_value<float>())
362 return 0.f;
363 return value;
364 }
365
366 /**
367 * Force already-denormal float value to zero
368 */
sanitize_denormal(float & value)369 inline void sanitize_denormal(float& value)
370 {
371 if (!std::isnormal(value))
372 value = 0.f;
373 }
374
375 /**
376 * Force already-denormal float value to zero
377 */
sanitize_denormal(double & value)378 inline void sanitize_denormal(double & value)
379 {
380 if (!std::isnormal(value))
381 value = 0.f;
382 }
383
384 /**
385 * Force "small enough" double value to zero
386 */
sanitize(double & value)387 inline void sanitize(double &value)
388 {
389 if (std::abs(value) < small_value<double>())
390 value = 0.0;
391 }
392
_sanitize(double value)393 inline double _sanitize(double value)
394 {
395 if (std::abs(value) < small_value<double>())
396 return 0.0;
397
398 return value;
399 }
400 /**
401 * Force "small enough" stereo value to zero
402 */
403 template<class T>
sanitize(stereo_sample<T> & value)404 inline void sanitize(stereo_sample<T> &value)
405 {
406 sanitize(value.left);
407 sanitize(value.right);
408 }
409
fract16(unsigned int value)410 inline float fract16(unsigned int value)
411 {
412 return (value & 0xFFFF) * (1.0 / 65536.0);
413 }
414
415 /**
416 * typical precalculated sine table
417 */
418 template<class T, int N, int Multiplier>
419 class sine_table
420 {
421 public:
422 static bool initialized;
423 static T data[N+1];
sine_table()424 sine_table() {
425 if (initialized)
426 return;
427 initialized = true;
428 for (int i=0; i<N+1; i++)
429 data[i] = (T)(Multiplier*sin(i*2*M_PI*(1.0/N)));
430 }
431 };
432
433 template<class T, int N, int Multiplier>
434 bool sine_table<T,N,Multiplier>::initialized = false;
435
436 template<class T, int N, int Multiplier>
437 T sine_table<T,N,Multiplier>::data[N+1];
438
439 /// fast float to int conversion using default rounding mode
fastf2i_drm(float f)440 inline int fastf2i_drm(float f)
441 {
442 #ifdef __X86__
443 volatile int v;
444 __asm ( "flds %1; fistpl %0" : "=m"(v) : "m"(f));
445 return v;
446 #else
447 return (int)nearbyintf(f);
448 #endif
449 }
450
451 /// Convert MIDI note to frequency in Hz.
452 inline float note_to_hz(double note, double detune_cents = 0.0)
453 {
454 return 440 * pow(2.0, (note - 69 + detune_cents/100.0) / 12.0);
455 }
456
457 /// Hermite interpolation between two points and slopes in normalized range (written after Wikipedia article)
458 /// @arg t normalized x coordinate (0-1 over the interval in question)
459 /// @arg p0 first point
460 /// @arg p1 second point
461 /// @arg m0 first slope (multiply by interval width when using over non-1-wide interval)
462 /// @arg m1 second slope (multiply by interval width when using over non-1-wide interval)
normalized_hermite(float t,float p0,float p1,float m0,float m1)463 inline float normalized_hermite(float t, float p0, float p1, float m0, float m1)
464 {
465 float t2 = t*t;
466 float t3 = t2*t;
467 return (2*t3 - 3*t2 + 1) * p0 + (t3 - 2*t2 + t) * m0 + (-2*t3 + 3*t2) * p1 + (t3-t2) * m1;
468 }
469
470 /// Hermite interpolation between two points and slopes
471 /// @arg x point within interval (x0 <= x <= x1)
472 /// @arg x0 interval start
473 /// @arg x1 interval end
474 /// @arg p0 value at x0
475 /// @arg p1 value at x1
476 /// @arg m0 slope (steepness, tangent) at x0
477 /// @arg m1 slope at x1
hermite_interpolation(float x,float x0,float x1,float p0,float p1,float m0,float m1)478 inline float hermite_interpolation(float x, float x0, float x1, float p0, float p1, float m0, float m1)
479 {
480 float width = x1 - x0;
481 float t = (x - x0) / width;
482 m0 *= width;
483 m1 *= width;
484 float t2 = t*t;
485 float t3 = t2*t;
486
487 float ct0 = p0;
488 float ct1 = m0;
489 float ct2 = -3 * p0 - 2 * m0 + 3 * p1 - m1;
490 float ct3 = 2 * p0 + m0 - 2 * p1 + m1;
491
492 return ct3 * t3 + ct2 * t2 + ct1 * t + ct0;
493 //return (2*t3 - 3*t2 + 1) * p0 + (t3 - 2*t2 + t) * m0 + (-2*t3 + 3*t2) * p1 + (t3-t2) * m1;
494 }
495
496 /// convert amplitude value to dB
amp2dB(float amp)497 inline float amp2dB(float amp)
498 {
499 return 20 * log10(amp);
500 }
501 /// convert dB to amplitude value
dB2amp(float db)502 inline float dB2amp(float db)
503 {
504 return exp((db / 20.0) * log(10.0));
505 }
506
507 /// print binary of any data type
508 /// assumes little endian
print_bits(size_t const size,void const * const ptr)509 inline void print_bits(size_t const size, void const * const ptr)
510 {
511 unsigned char *b = (unsigned char*) ptr;
512 unsigned char byte;
513 for (int i = size - 1; i >=0 ; i--) {
514 for (int j = 7; j >= 0; j--) {
515 byte = b[i] & (1<<j);
516 byte >>= j;
517 printf("%u", byte);
518 }
519 }
520 puts("");
521 }
522
523
524 struct note_desc
525 {
526 int note;
527 double cents;
528 double freq;
529 int octave;
530 const char *name;
531 };
532
hz_to_note(double hz,double tune)533 inline note_desc hz_to_note (double hz, double tune)
534 {
535 note_desc desc;
536 static const char notenames[] = "C\0\0C#\0D\0\0D#\0E\0\0F\0\0F#\0G\0\0G#\0A\0\0A#\0B\0\0";
537 double f2 = log2(hz / tune);
538 double cn = fmod(f2 * 1200., 100.);
539 desc.freq = hz;
540 desc.note = std::max(0., round(12 * f2 + 69));
541 desc.name = notenames + (desc.note % 12) * 3;
542 desc.cents = (cn < -50) ? 100 + cn : (cn > 50) ? -(100 - cn) : cn;
543 desc.octave = int(desc.note / 12) - 1;
544 return desc;
545 }
546
547
548 enum periodic_unit { UNIT_BPM, UNIT_MS, UNIT_HZ, UNIT_SYNC };
549
convert_periodic(double val,periodic_unit unit_in,periodic_unit unit_out)550 inline double convert_periodic (double val, periodic_unit unit_in, periodic_unit unit_out)
551 {
552 // calculates different periodical units into each other.
553 // it is used for e.g. pulsator or vintage delay to unify
554 // the selected timing method
555 if (unit_in == unit_out)
556 return val;
557 double freq = 0.;
558 switch (unit_in) {
559 case UNIT_BPM: freq = val / 60.; break;
560 case UNIT_MS: freq = 1. / (val / 1000.); break;
561 case UNIT_HZ: freq = val; break;
562 case UNIT_SYNC: freq = val / 60.; break;
563 }
564 switch (unit_out) {
565 default:
566 case UNIT_BPM: return freq * 60.;
567 case UNIT_MS: return (1. / freq) / 1000.;
568 case UNIT_HZ: return freq;
569 case UNIT_SYNC: return freq * 60.;
570 }
571 };
572
573
574
575 };
576 #endif
577