4 * Copyright (C) 2001-2007 Krzysztof Foltman
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.
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.
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.
21 #ifndef __CALF_PRIMITIVES_H
22 #define __CALF_PRIMITIVES_H
34 /// Set a float to zero
35 inline void zero(float &v
) {
39 /// Set a double to zero
40 inline void zero(double &v
) {
44 /// Set 64-bit unsigned integer value to zero
45 inline void zero(uint64_t &v
) { v
= 0; };
46 /// Set 32-bit unsigned integer value to zero
47 inline void zero(uint32_t &v
) { v
= 0; };
48 /// Set 16-bit unsigned integer value to zero
49 inline void zero(uint16_t &v
) { v
= 0; };
50 /// Set 8-bit unsigned integer value to zero
51 inline void zero(uint8_t &v
) { v
= 0; };
52 /// Set 64-bit signed integer value to zero
53 inline void zero(int64_t &v
) { v
= 0; };
54 /// Set 32-bit signed integer value to zero
55 inline void zero(int32_t &v
) { v
= 0; };
56 /// Set 16-bit signed integer value to zero
57 inline void zero(int16_t &v
) { v
= 0; };
58 /// Set 8-bit signed integer value to zero
59 inline void zero(int8_t &v
) { v
= 0; };
61 /// Set array (buffer or anything similar) to vector of zeroes
63 void zero(T
*data
, unsigned int size
) {
66 for (unsigned int i
=0; i
<size
; i
++)
70 /// Set array (buffer or anything similar) to vector of values
72 void fill(T
*data
, T value
, unsigned int size
) {
73 for (unsigned int i
=0; i
<size
; i
++)
77 template<class T
= float>struct stereo_sample
{
80 /// default constructor - preserves T's semantics (ie. no implicit initialization to 0)
81 inline stereo_sample() {
83 inline stereo_sample(T _left
, T _right
) {
87 inline stereo_sample(T _both
) {
91 inline stereo_sample(const stereo_sample
<U
> &value
) {
95 inline stereo_sample
& operator=(const T
&value
) {
100 inline stereo_sample
& operator=(const stereo_sample
<U
> &value
) {
106 inline operator T() const {
107 return (left+right)/2;
110 inline stereo_sample
& operator*=(const T
&multiplier
) {
115 inline stereo_sample
& operator+=(const stereo_sample
<T
> &value
) {
117 right
+= value
.right
;
120 inline stereo_sample
& operator-=(const stereo_sample
<T
> &value
) {
122 right
-= value
.right
;
125 template<typename U
> inline stereo_sample
<U
> operator*(const U
&value
) const {
126 return stereo_sample
<U
>(left
*value
, right
*value
);
128 /*inline stereo_sample<float> operator*(float value) const {
129 return stereo_sample<float>(left*value, right*value);
131 inline stereo_sample<double> operator*(double value) const {
132 return stereo_sample<double>(left*value, right*value);
134 inline stereo_sample
<T
> operator+(const stereo_sample
<T
> &value
) {
135 return stereo_sample(left
+value
.left
, right
+value
.right
);
137 inline stereo_sample
<T
> operator-(const stereo_sample
<T
> &value
) {
138 return stereo_sample(left
-value
.left
, right
-value
.right
);
140 inline stereo_sample
<T
> operator+(const T
&value
) {
141 return stereo_sample(left
+value
, right
+value
);
143 inline stereo_sample
<T
> operator-(const T
&value
) {
144 return stereo_sample(left
-value
, right
-value
);
146 inline stereo_sample
<float> operator+(float value
) {
147 return stereo_sample
<float>(left
+value
, right
+value
);
149 inline stereo_sample
<float> operator-(float value
) {
150 return stereo_sample
<float>(left
-value
, right
-value
);
152 inline stereo_sample
<double> operator+(double value
) {
153 return stereo_sample
<double>(left
+value
, right
+value
);
155 inline stereo_sample
<double> operator-(double value
) {
156 return stereo_sample
<double>(left
-value
, right
-value
);
160 /// Multiply constant by stereo_value
162 inline stereo_sample
<T
> operator*(const T
&value
, const stereo_sample
<T
> &value2
) {
163 return stereo_sample
<T
>(value2
.left
*value
, value2
.right
*value
);
166 /// Add constant to stereo_value
168 inline stereo_sample
<T
> operator+(const T
&value
, const stereo_sample
<T
> &value2
) {
169 return stereo_sample
<T
>(value2
.left
+value
, value2
.right
+value
);
172 /// Subtract stereo_value from constant (yields stereo_value of course)
174 inline stereo_sample
<T
> operator-(const T
&value
, const stereo_sample
<T
> &value2
) {
175 return stereo_sample
<T
>(value
-value2
.left
, value
-value2
.right
);
178 /// Shift value right by 'bits' bits (multiply by 2^-bits)
180 inline stereo_sample
<T
> shr(stereo_sample
<T
> v
, int bits
= 1) {
181 v
.left
= shr(v
.left
, bits
);
182 v
.right
= shr(v
.right
, bits
);
186 /// Set a stereo_sample<T> value to zero
188 inline void zero(stereo_sample
<T
> &v
) {
193 /// 'Small value' for integer and other types
195 inline T
small_value() {
199 /// '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 inline float small_value
<float>() {
202 return (1.0/16777216.0); // allows for 2^-24, should be enough for 24-bit DACs at least :)
205 /// 'Small value' for doubles (2^-24) - used for primitive underrun prevention. The value is pretty much arbitrary.
207 inline double small_value
<double>() {
208 return (1.0/16777216.0);
211 /// Convert a single value to single value = do nothing :) (but it's a generic with specialisation for stereo_sample)
213 inline float mono(T v
) {
217 /// Convert a stereo_sample to single value by averaging two channels
219 inline T
mono(stereo_sample
<T
> v
) {
220 return shr(v
.left
+v
.right
);
223 /// Clip a value to [min, max]
225 inline T
clip(T value
, T min
, T max
) {
226 if (value
< min
) return min
;
227 if (value
> max
) return max
;
231 /// Clip a double to [-1.0, +1.0]
232 inline double clip11(double value
) {
233 double a
= fabs(value
);
234 if (a
<=1) return value
;
235 return (value
<0) ? -1.0 : 1.0;
238 /// Clip a float to [-1.0f, +1.0f]
239 inline float clip11(float value
) {
240 float a
= fabsf(value
);
241 if (a
<=1) return value
;
242 return (value
<0) ? -1.0f
: 1.0f
;
245 /// Clip a double to [0.0, +1.0]
246 inline double clip01(double value
) {
247 double a
= fabs(value
-0.5);
248 if (a
<=0.5) return value
;
249 return (a
<0) ? -0.0 : 1.0;
252 /// Clip a float to [0.0f, +1.0f]
253 inline float clip01(float value
) {
254 float a
= fabsf(value
-0.5f
);
255 if (a
<=0.5f
) return value
;
256 return (value
< 0) ? -0.0f
: 1.0f
;
259 // Linear interpolation (mix-way between v1 and v2).
260 template<typename T
, typename U
>
261 inline T
lerp(T v1
, T v2
, U mix
) {
262 return v1
+(v2
-v1
)*mix
;
265 // Linear interpolation for stereo values (mix-way between v1 and v2).
267 inline stereo_sample
<T
> lerp(stereo_sample
<T
> &v1
, stereo_sample
<T
> &v2
, float mix
) {
268 return stereo_sample
<T
>(v1
.left
+(v2
.left
-v1
.left
)*mix
, v1
.right
+(v2
.right
-v1
.right
)*mix
);
272 * decay-only envelope (linear or exponential); deactivates itself when it goes below a set point (epsilon)
276 double value
, initial
;
277 unsigned int age
, mask
;
283 initial
= value
= 0.0;
285 inline bool get_active() {
288 inline double get() {
289 return active
? value
: 0.0;
291 inline void set(double v
) {
296 /// reinitialise envelope (must be called if shape changes from linear to exponential or vice versa in the middle of envelope)
302 inline void add(double v
) {
311 static inline double calc_exp_constant(double times
, double cycles
)
315 return pow(times
, 1.0 / cycles
);
317 inline void age_exp(double constant
, double epsilon
) {
320 value
= initial
* pow(constant
, (double)age
);
328 inline void age_lin(double constant
, double epsilon
) {
331 value
= initial
- constant
* age
;
339 inline void deactivate() {
349 virtual void execute(scheduler
*s
)=0;
350 virtual void dispose() { delete this; }
354 /// this scheduler is based on std::multimap, so it isn't very fast, I guess
355 /// maybe some day it should be rewritten to use heapsort or something
356 /// work in progress, don't use!
358 std::multimap
<unsigned int, task
*> timeline
;
359 unsigned int time
, next_task
;
361 class end_buf_task
: public task
{
364 end_buf_task(scheduler
*_p
) : p(_p
) {}
365 virtual void execute(scheduler
*s
) { p
->eob
= true; }
366 virtual void dispose() { }
372 , next_task((unsigned)-1)
377 next_task
= (unsigned)-1;
380 inline bool is_next_tick() {
381 if (time
< next_task
)
386 inline void next_tick() {
389 void set(int pos
, task
*t
) {
390 timeline
.insert(std::pair
<unsigned int, task
*>(time
+pos
, t
));
391 next_task
= timeline
.begin()->first
;
394 std::multimap
<unsigned int, task
*>::iterator i
= timeline
.begin();
395 while(i
!= timeline
.end() && i
->first
== time
) {
396 i
->second
->execute(this);
397 i
->second
->dispose();
404 void set_buffer_size(int count
) {
410 * Force "small enough" float value to zero
412 inline void sanitize(float &value
)
415 if (std::abs(value
) < small_value
<float>())
418 const int val
= *reinterpret_cast <const int *> (&value
);
419 if ((val
& 0x7F800000) == 0 && (val
& 0x007FFFFF) != 0)
422 inline float _sanitize(float value
)
424 if (std::abs(value
) < small_value
<float>())
430 * Force already-denormal float value to zero
432 inline void sanitize_denormal(float& value
)
434 if (!std::isnormal(value
))
439 * Force already-denormal float value to zero
441 inline void sanitize_denormal(double & value
)
443 if (!std::isnormal(value
))
448 * Force "small enough" double value to zero
450 inline void sanitize(double &value
)
452 if (std::abs(value
) < small_value
<double>())
456 inline double _sanitize(double value
)
458 if (std::abs(value
) < small_value
<double>())
464 * Force "small enough" stereo value to zero
467 inline void sanitize(stereo_sample
<T
> &value
)
469 sanitize(value
.left
);
470 sanitize(value
.right
);
473 inline float fract16(unsigned int value
)
475 return (value
& 0xFFFF) * (1.0 / 65536.0);
479 * typical precalculated sine table
481 template<class T
, int N
, int Multiplier
>
485 static bool initialized
;
491 for (int i
=0; i
<N
+1; i
++)
492 data
[i
] = (T
)(Multiplier
*sin(i
*2*M_PI
*(1.0/N
)));
496 template<class T
, int N
, int Multiplier
>
497 bool sine_table
<T
,N
,Multiplier
>::initialized
= false;
499 template<class T
, int N
, int Multiplier
>
500 T sine_table
<T
,N
,Multiplier
>::data
[N
+1];
502 /// fast float to int conversion using default rounding mode
503 inline int fastf2i_drm(float f
)
507 __asm ( "flds %1; fistpl %0" : "=m"(v
) : "m"(f
));
510 return (int)nearbyintf(f
);
514 /// Convert MIDI note to frequency in Hz.
515 inline float note_to_hz(double note
, double detune_cents
= 0.0)
517 return 440 * pow(2.0, (note
- 69 + detune_cents
/100.0) / 12.0);
520 /// Hermite interpolation between two points and slopes in normalized range (written after Wikipedia article)
521 /// @arg t normalized x coordinate (0-1 over the interval in question)
522 /// @arg p0 first point
523 /// @arg p1 second point
524 /// @arg m0 first slope (multiply by interval width when using over non-1-wide interval)
525 /// @arg m1 second slope (multiply by interval width when using over non-1-wide interval)
526 inline float normalized_hermite(float t
, float p0
, float p1
, float m0
, float m1
)
530 return (2*t3
- 3*t2
+ 1) * p0
+ (t3
- 2*t2
+ t
) * m0
+ (-2*t3
+ 3*t2
) * p1
+ (t3
-t2
) * m1
;
533 /// Hermite interpolation between two points and slopes
534 /// @arg x point within interval (x0 <= x <= x1)
535 /// @arg x0 interval start
536 /// @arg x1 interval end
537 /// @arg p0 value at x0
538 /// @arg p1 value at x1
539 /// @arg m0 slope (steepness, tangent) at x0
540 /// @arg m1 slope at x1
541 inline float hermite_interpolation(float x
, float x0
, float x1
, float p0
, float p1
, float m0
, float m1
)
543 float width
= x1
- x0
;
544 float t
= (x
- x0
) / width
;
552 float ct2
= -3 * p0
- 2 * m0
+ 3 * p1
- m1
;
553 float ct3
= 2 * p0
+ m0
- 2 * p1
+ m1
;
555 return ct3
* t3
+ ct2
* t2
+ ct1
* t
+ ct0
;
556 //return (2*t3 - 3*t2 + 1) * p0 + (t3 - 2*t2 + t) * m0 + (-2*t3 + 3*t2) * p1 + (t3-t2) * m1;
559 /// convert amplitude value to dB
560 inline float amp2dB(float amp
)
562 return 20 * log10(amp
);
564 /// convert dB to amplitude value
565 inline float dB2amp(float db
)
567 return exp((db
/ 20.0) * log(10.0));
570 /// print binary of any data type
571 /// assumes little endian
572 inline void print_bits(size_t const size
, void const * const ptr
)
574 unsigned char *b
= (unsigned char*) ptr
;
576 for (int i
= size
- 1; i
>=0 ; i
--) {
577 for (int j
= 7; j
>= 0; j
--) {
578 byte
= b
[i
] & (1<<j
);
596 inline note_desc
hz_to_note (double hz
, double tune
)
599 static const char notenames
[] = "C\0\0C#\0D\0\0D#\0E\0\0F\0\0F#\0G\0\0G#\0A\0\0A#\0B\0\0";
600 double f2
= hz
/ tune
;
601 double lf2
= logf(f2
);
602 double rf2
= 1200 * lf2
/ logf(2.f
) - 300;
603 rf2
-= 1200.f
* floor(rf2
/ 1200.f
);
604 int note
= round(rf2
/ 100.f
);
608 int mnote
= round(12 * log2(f2
)) + 57;
612 desc
.octave
= int(mnote
/ 12) - 2;
613 desc
.name
= notenames
+ (mnote
% 12) * 3;