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
32 namespace dsp {
33
34 /// Set a float to zero
zero(float & v)35 inline void zero(float &v) {
36 v = 0;
37 };
38
39 /// Set a double to zero
zero(double & v)40 inline void zero(double &v) {
41 v = 0;
42 };
43
44 /// Set 64-bit unsigned integer value to zero
zero(uint64_t & v)45 inline void zero(uint64_t &v) { v = 0; };
46 /// Set 32-bit unsigned integer value to zero
zero(uint32_t & v)47 inline void zero(uint32_t &v) { v = 0; };
48 /// Set 16-bit unsigned integer value to zero
zero(uint16_t & v)49 inline void zero(uint16_t &v) { v = 0; };
50 /// Set 8-bit unsigned integer value to zero
zero(uint8_t & v)51 inline void zero(uint8_t &v) { v = 0; };
52 /// Set 64-bit signed integer value to zero
zero(int64_t & v)53 inline void zero(int64_t &v) { v = 0; };
54 /// Set 32-bit signed integer value to zero
zero(int32_t & v)55 inline void zero(int32_t &v) { v = 0; };
56 /// Set 16-bit signed integer value to zero
zero(int16_t & v)57 inline void zero(int16_t &v) { v = 0; };
58 /// Set 8-bit signed integer value to zero
zero(int8_t & v)59 inline void zero(int8_t &v) { v = 0; };
60
61 /// Set array (buffer or anything similar) to vector of zeroes
62 template<class T>
zero(T * data,unsigned int size)63 void zero(T *data, unsigned int size) {
64 T value;
65 dsp::zero(value);
66 for (unsigned int i=0; i<size; i++)
67 *data++ = value;
68 }
69
70 template<class T = float>struct stereo_sample {
71 T left;
72 T right;
73 /// default constructor - preserves T's semantics (ie. no implicit initialization to 0)
stereo_samplestereo_sample74 inline stereo_sample() {
75 }
stereo_samplestereo_sample76 inline stereo_sample(T _left, T _right) {
77 left = _left;
78 right = _right;
79 }
stereo_samplestereo_sample80 inline stereo_sample(T _both) {
81 left = right = _both;
82 }
83 template<typename U>
stereo_samplestereo_sample84 inline stereo_sample(const stereo_sample<U> &value) {
85 left = value.left;
86 right = value.right;
87 }
88 inline stereo_sample& operator=(const T &value) {
89 left = right = value;
90 return *this;
91 }
92 template<typename U>
93 inline stereo_sample& operator=(const stereo_sample<U> &value) {
94 left = value.left;
95 right = value.right;
96 return *this;
97 }
98 /*
99 inline operator T() const {
100 return (left+right)/2;
101 }
102 */
103 inline stereo_sample& operator*=(const T &multiplier) {
104 left *= multiplier;
105 right *= multiplier;
106 return *this;
107 }
108 inline stereo_sample& operator+=(const stereo_sample<T> &value) {
109 left += value.left;
110 right += value.right;
111 return *this;
112 }
113 inline stereo_sample& operator-=(const stereo_sample<T> &value) {
114 left -= value.left;
115 right -= value.right;
116 return *this;
117 }
118 template<typename U> inline stereo_sample<U> operator*(const U &value) const {
119 return stereo_sample<U>(left*value, right*value);
120 }
121 /*inline stereo_sample<float> operator*(float value) const {
122 return stereo_sample<float>(left*value, right*value);
123 }
124 inline stereo_sample<double> operator*(double value) const {
125 return stereo_sample<double>(left*value, right*value);
126 }*/
127 inline stereo_sample<T> operator+(const stereo_sample<T> &value) {
128 return stereo_sample(left+value.left, right+value.right);
129 }
130 inline stereo_sample<T> operator-(const stereo_sample<T> &value) {
131 return stereo_sample(left-value.left, right-value.right);
132 }
133 inline stereo_sample<T> operator+(const T &value) {
134 return stereo_sample(left+value, right+value);
135 }
136 inline stereo_sample<T> operator-(const T &value) {
137 return stereo_sample(left-value, right-value);
138 }
139 inline stereo_sample<float> operator+(float value) {
140 return stereo_sample<float>(left+value, right+value);
141 }
142 inline stereo_sample<float> operator-(float value) {
143 return stereo_sample<float>(left-value, right-value);
144 }
145 inline stereo_sample<double> operator+(double value) {
146 return stereo_sample<double>(left+value, right+value);
147 }
148 inline stereo_sample<double> operator-(double value) {
149 return stereo_sample<double>(left-value, right-value);
150 }
151 };
152
153 /// Multiply constant by stereo_value
154 template<class T>
155 inline stereo_sample<T> operator*(const T &value, const stereo_sample<T> &value2) {
156 return stereo_sample<T>(value2.left*value, value2.right*value);
157 }
158
159 /// Add constant to stereo_value
160 template<class T>
161 inline stereo_sample<T> operator+(const T &value, const stereo_sample<T> &value2) {
162 return stereo_sample<T>(value2.left+value, value2.right+value);
163 }
164
165 /// Subtract stereo_value from constant (yields stereo_value of course)
166 template<class T>
167 inline stereo_sample<T> operator-(const T &value, const stereo_sample<T> &value2) {
168 return stereo_sample<T>(value-value2.left, value-value2.right);
169 }
170
171 /// Shift value right by 'bits' bits (multiply by 2^-bits)
172 template<typename T>
173 inline stereo_sample<T> shr(stereo_sample<T> v, int bits = 1) {
174 v.left = shr(v.left, bits);
175 v.right = shr(v.right, bits);
176 return v;
177 }
178
179 /// Set a stereo_sample<T> value to zero
180 template<typename T>
zero(stereo_sample<T> & v)181 inline void zero(stereo_sample<T> &v) {
182 dsp::zero(v.left);
183 dsp::zero(v.right);
184 }
185
186 /// 'Small value' for integer and other types
187 template<typename T>
small_value()188 inline T small_value() {
189 return 0;
190 }
191
192 /// '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).
193 template<>
194 inline float small_value<float>() {
195 return (1.0/16777216.0); // allows for 2^-24, should be enough for 24-bit DACs at least :)
196 }
197
198 /// 'Small value' for doubles (2^-24) - used for primitive underrun prevention. The value is pretty much arbitrary.
199 template<>
200 inline double small_value<double>() {
201 return (1.0/16777216.0);
202 }
203
204 /// Convert a single value to single value = do nothing :) (but it's a generic with specialisation for stereo_sample)
205 template<typename T>
mono(T v)206 inline float mono(T v) {
207 return v;
208 }
209
210 /// Convert a stereo_sample to single value by averaging two channels
211 template<typename T>
mono(stereo_sample<T> v)212 inline T mono(stereo_sample<T> v) {
213 return shr(v.left+v.right);
214 }
215
216 /// Clip a value to [min, max]
217 template<typename T>
clip(T value,T min,T max)218 inline T clip(T value, T min, T max) {
219 if (value < min) return min;
220 if (value > max) return max;
221 return value;
222 }
223
224 /// Clip a double to [-1.0, +1.0]
clip11(double value)225 inline double clip11(double value) {
226 double a = fabs(value);
227 if (a<=1) return value;
228 return (value<0) ? -1.0 : 1.0;
229 }
230
231 /// Clip a float to [-1.0f, +1.0f]
clip11(float value)232 inline float clip11(float value) {
233 float a = fabsf(value);
234 if (a<=1) return value;
235 return (value<0) ? -1.0f : 1.0f;
236 }
237
238 /// Clip a double to [0.0, +1.0]
clip01(double value)239 inline double clip01(double value) {
240 double a = fabs(value-0.5);
241 if (a<=0.5) return value;
242 return (a<0) ? -0.0 : 1.0;
243 }
244
245 /// Clip a float to [0.0f, +1.0f]
clip01(float value)246 inline float clip01(float value) {
247 float a = fabsf(value-0.5f);
248 if (a<=0.5f) return value;
249 return (value < 0) ? -0.0f : 1.0f;
250 }
251
252 // Linear interpolation (mix-way between v1 and v2).
253 template<typename T, typename U>
lerp(T v1,T v2,U mix)254 inline T lerp(T v1, T v2, U mix) {
255 return v1+(v2-v1)*mix;
256 }
257
258 // Linear interpolation for stereo values (mix-way between v1 and v2).
259 template<typename T>
lerp(stereo_sample<T> & v1,stereo_sample<T> & v2,float mix)260 inline stereo_sample<T> lerp(stereo_sample<T> &v1, stereo_sample<T> &v2, float mix) {
261 return stereo_sample<T>(v1.left+(v2.left-v1.left)*mix, v1.right+(v2.right-v1.right)*mix);
262 }
263
264 /**
265 * decay-only envelope (linear or exponential); deactivates itself when it goes below a set point (epsilon)
266 */
267 class decay
268 {
269 double value, initial;
270 unsigned int age, mask;
271 bool active;
272 public:
decay()273 decay() {
274 active = false;
275 mask = 127;
276 initial = value = 0.0;
277 }
get_active()278 inline bool get_active() {
279 return active;
280 }
get()281 inline double get() {
282 return active ? value : 0.0;
283 }
set(double v)284 inline void set(double v) {
285 initial = value = v;
286 active = true;
287 age = 0;
288 }
289 /// reinitialise envelope (must be called if shape changes from linear to exponential or vice versa in the middle of envelope)
reinit()290 inline void reinit()
291 {
292 initial = value;
293 age = 1;
294 }
add(double v)295 inline void add(double v) {
296 if (active)
297 value += v;
298 else
299 value = v;
300 initial = value;
301 age = 0;
302 active = true;
303 }
calc_exp_constant(double times,double cycles)304 static inline double calc_exp_constant(double times, double cycles)
305 {
306 if (cycles < 1.0)
307 cycles = 1.0;
308 return pow(times, 1.0 / cycles);
309 }
age_exp(double constant,double epsilon)310 inline void age_exp(double constant, double epsilon) {
311 if (active) {
312 if (!(age & mask))
313 value = initial * pow(constant, (double)age);
314 else
315 value *= constant;
316 if (value < epsilon)
317 active = false;
318 age++;
319 }
320 }
age_lin(double constant,double epsilon)321 inline void age_lin(double constant, double epsilon) {
322 if (active) {
323 if (!(age & mask))
324 value = initial - constant * age;
325 else
326 value -= constant;
327 if (value < epsilon)
328 active = false;
329 age++;
330 }
331 }
deactivate()332 inline void deactivate() {
333 active = false;
334 value = 0;
335 }
336 };
337
338 class scheduler;
339
340 class task {
341 public:
342 virtual void execute(scheduler *s)=0;
dispose()343 virtual void dispose() { delete this; }
~task()344 virtual ~task() {}
345 };
346
347 /// this scheduler is based on std::multimap, so it isn't very fast, I guess
348 /// maybe some day it should be rewritten to use heapsort or something
349 /// work in progress, don't use!
350 class scheduler {
351 std::multimap<unsigned int, task *> timeline;
352 unsigned int time, next_task;
353 bool eob;
354 class end_buf_task: public task {
355 public:
356 scheduler *p;
end_buf_task(scheduler * _p)357 end_buf_task(scheduler *_p) : p(_p) {}
execute(scheduler * s)358 virtual void execute(scheduler *s) { p->eob = true; }
dispose()359 virtual void dispose() { }
360 } eobt;
361 public:
362
scheduler()363 scheduler()
364 : time(0)
365 , next_task((unsigned)-1)
366 , eob(true)
367 , eobt (this)
368 {
369 time = 0;
370 next_task = (unsigned)-1;
371 eob = false;
372 }
is_next_tick()373 inline bool is_next_tick() {
374 if (time < next_task)
375 return true;
376 do_tasks();
377 }
next_tick()378 inline void next_tick() {
379 time++;
380 }
set(int pos,task * t)381 void set(int pos, task *t) {
382 timeline.insert(std::pair<unsigned int, task *>(time+pos, t));
383 next_task = timeline.begin()->first;
384 }
do_tasks()385 void do_tasks() {
386 std::multimap<unsigned int, task *>::iterator i = timeline.begin();
387 while(i != timeline.end() && i->first == time) {
388 i->second->execute(this);
389 i->second->dispose();
390 timeline.erase(i);
391 }
392 }
is_eob()393 bool is_eob() {
394 return eob;
395 }
set_buffer_size(int count)396 void set_buffer_size(int count) {
397 set(count, &eobt);
398 }
399 };
400
401 /**
402 * Force "small enough" float value to zero
403 */
sanitize(float & value)404 inline void sanitize(float &value)
405 {
406 if (std::abs(value) < small_value<float>())
407 value = 0.f;
408 }
409
410 /**
411 * Force already-denormal float value to zero
412 */
sanitize_denormal(float & value)413 inline void sanitize_denormal(float& value)
414 {
415 if (((*(unsigned int *) &value) & 0x7f800000) == 0) {
416 value = 0;
417 }
418 }
419
420 /**
421 * Force "small enough" double value to zero
422 */
sanitize(double & value)423 inline void sanitize(double &value)
424 {
425 if (std::abs(value) < small_value<double>())
426 value = 0.f;
427 }
428
429 /**
430 * Force "small enough" stereo value to zero
431 */
432 template<class T>
sanitize(stereo_sample<T> & value)433 inline void sanitize(stereo_sample<T> &value)
434 {
435 sanitize(value.left);
436 sanitize(value.right);
437 }
438
fract16(unsigned int value)439 inline float fract16(unsigned int value)
440 {
441 return (value & 0xFFFF) * (1.0 / 65536.0);
442 }
443
444 /**
445 * typical precalculated sine table
446 */
447 template<class T, int N, int Multiplier>
448 class sine_table
449 {
450 public:
451 static bool initialized;
452 static T data[N+1];
sine_table()453 sine_table() {
454 if (initialized)
455 return;
456 initialized = true;
457 for (int i=0; i<N+1; i++)
458 data[i] = (T)(Multiplier*sin(i*2*M_PI*(1.0/N)));
459 }
460 };
461
462 template<class T, int N, int Multiplier>
463 bool sine_table<T,N,Multiplier>::initialized = false;
464
465 template<class T, int N, int Multiplier>
466 T sine_table<T,N,Multiplier>::data[N+1];
467
468 /// fast float to int conversion using default rounding mode
fastf2i_drm(float f)469 inline int fastf2i_drm(float f)
470 {
471 #ifdef __X86__
472 volatile int v;
473 __asm ( "flds %1; fistpl %0" : "=m"(v) : "m"(f));
474 return v;
475 #else
476 return (int)nearbyintf(f);
477 #endif
478 }
479
480 /// Convert MIDI note to frequency in Hz.
481 inline float note_to_hz(double note, double detune_cents = 0.0)
482 {
483 return 440 * pow(2.0, (note - 69 + detune_cents/100.0) / 12.0);
484 }
485
486 /// Hermite interpolation between two points and slopes in normalized range (written after Wikipedia article)
487 /// @arg t normalized x coordinate (0-1 over the interval in question)
488 /// @arg p0 first point
489 /// @arg p1 second point
490 /// @arg m0 first slope (multiply by interval width when using over non-1-wide interval)
491 /// @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)492 inline float normalized_hermite(float t, float p0, float p1, float m0, float m1)
493 {
494 float t2 = t*t;
495 float t3 = t2*t;
496 return (2*t3 - 3*t2 + 1) * p0 + (t3 - 2*t2 + t) * m0 + (-2*t3 + 3*t2) * p1 + (t3-t2) * m1;
497 }
498
499 /// Hermite interpolation between two points and slopes
500 /// @arg x point within interval (x0 <= x <= x1)
501 /// @arg x0 interval start
502 /// @arg x1 interval end
503 /// @arg p0 value at x0
504 /// @arg p1 value at x1
505 /// @arg m0 slope (steepness, tangent) at x0
506 /// @arg m1 slope at x1
hermite_interpolation(float x,float x0,float x1,float p0,float p1,float m0,float m1)507 inline float hermite_interpolation(float x, float x0, float x1, float p0, float p1, float m0, float m1)
508 {
509 float width = x1 - x0;
510 float t = (x - x0) / width;
511 m0 *= width;
512 m1 *= width;
513 float t2 = t*t;
514 float t3 = t2*t;
515
516 float ct0 = p0;
517 float ct1 = m0;
518 float ct2 = -3 * p0 - 2 * m0 + 3 * p1 - m1;
519 float ct3 = 2 * p0 + m0 - 2 * p1 + m1;
520
521 return ct3 * t3 + ct2 * t2 + ct1 * t + ct0;
522 //return (2*t3 - 3*t2 + 1) * p0 + (t3 - 2*t2 + t) * m0 + (-2*t3 + 3*t2) * p1 + (t3-t2) * m1;
523 }
524
525 /// convert amplitude value to dB
amp2dB(float amp)526 inline float amp2dB(float amp)
527 {
528 return 6.0 * log(amp) / log(2);
529 }
530
531 };
532
533 #endif
534