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