Mozzi  version v2.0
sound synthesis library for Arduino
mozzi_fixmath.cpp
1 /*
2  * mozzi_fixmath.cpp
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2012-2024 Tim Barrass and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10  */
11 
12 #include "mozzi_fixmath.h"
13 
14 /** @ingroup fixmath
15 @{
16 */
17 
18 //Snipped from http://code.google.com/p/ht1632c/wiki/Optimizations
19 //TB2012 changed names to not interfere with arduino compilation
20 //Fast integer math
21 //
22 //If you need to include arithmetic operations in you code but you don't need
23 //floating point operations, you could use boolean operations instead of arithmetic
24 //operations, or use smaller data types and custom functions instead of stdlib functions
25 //or C operators (expecially / and %).
26 //Look at IntegerCodeSnippets, http://code.google.com/p/ht1632c/wiki/IntegerCodeSnippets
27 //
28 //Here is some ready to use fast integer 1 uint8_t wide math functions (from ht1632c library).
29 
30 /**
31 fast uint8_t modulus
32 @param n numerator
33 @param d denominator
34 @return modulus
35 */
37 {
38  while(n >= d)
39  n -= d;
40  return n;
41 }
42 
43 /** Fast uint8_t division
44 @param n numerator
45 @param d denominator
46 @return quotient
47 */
49 {
50  uint8_t q = 0;
51  while(n >= d)
52  {
53  n -= d;
54  q++;
55  }
56  return q;
57 }
58 
59 /* fast integer (1 uint8_t) PRNG */
60 uint8_t uint8_tRnd(uint8_t min, uint8_t max)
61 {
62  static uint8_t seed;
63  seed = (21 * seed + 21);
64  return min + uint8_tMod(seed, --max);
65 }
66 //WARNING: don't use this uint8_tRnd() function for cryptography!
67 
68 //} of snip from http://code.google.com/p/ht1632c/wiki/Optimizations
69 
70 
71 
72 // from http://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int
73 /* Exponentiation by squaring.
74 */
75 int ipow(int base, int exp)
76 {
77  int result = 1;
78  while (exp)
79  {
80  if (exp & 1)
81  result *= base;
82  exp >>= 1;
83  base *= base;
84  }
85 
86  return result;
87 }
88 
89 
90 /*
91 from: http://objectmix.com/vhdl/189970-2-powerof-x-where-x-fixed-point-value-2.html
92 
93 to do 2^(x.y) first find
94 2^x and 2^(x+1) through bit shifting 1 to the left by x and (x + 1) places
95 
96 now you do linear interpolation by drawing a line through these two points 2^x,
97 2^(x+1), then use f = m*x+b. the slope, m = rise over run
98 = (2^(x+1) - 2^x)/((x+1) - (x))
99 = 2^(x) * (2 - 1) / 1
100 = 2^(x)
101 b = 2^x, so to linearly interpolate do....(edited out typo)..
102 f = 2^(x) * (y) + 2^x
103 = 2^x * (y + 1)
104 where x is integer part, y is fractional part
105 */
106 
107 
108 /**
109 fast replacement for pow(2,x), where x is a Q8n8 fractional
110 fixed-point exponent. It's less accurate than pow(2,x), but useful where a
111 tradeoff between accuracy and speed is required to keep audio from glitching.
112 @param exponent in Q8n8 format.
113 @return pow(2,x) in Q16n16 format.
114 @todo Q16n16_pow2() accuracy needs more attention.
115 */
116 Q16n16 Q16n16_pow2(Q8n8 exponent)
117 {
118  // to do 2^(x.y) first find
119  //2^x and 2^(x+1) through bit shifting 1 to the left by x and (x + 1) places
120  uint8_t Q = (uint8_t)((Q8n8)exponent>>8); // integer part
121  uint8_t n = (uint8_t) exponent; // fractional part
122  // f = 2^x * (y + 1)
123  return (((Q16n16)Q8n8_FIX1 << Q) * (Q8n8_FIX1 + n));
124 }
125 
126 
127 
128 
129 //http://www.codecodex.com/wiki/Calculate_an_integer_square_root
130 //see Integer Square Roots by Jack W. Crenshaw, figure 2, http://www.embedded.com/electronics-blogs/programmer-s-toolbox/4219659/Integer-Square-Roots
131 
132 uint32_t // OR uint16 OR uint8_t
133 isqrt32 (uint32_t n) // OR isqrt16 ( uint16_t n ) OR isqrt8 ( uint8_t n ) - respectively [ OR overloaded as isqrt (uint16_t?? n) in C++ ]
134 {
135  uint32_t // OR register uint16_t OR register uint8_t - respectively
136  root, remainder, place;
137 
138  root = 0;
139  remainder = n;
140  place = 0x40000000; // OR place = 0x4000; OR place = 0x40; - respectively
141 
142  while (place > remainder)
143  place = place >> 2;
144  while (place)
145  {
146  if (remainder >= root + place)
147  {
148  remainder = remainder - root - place;
149  root = root + (place << 1);
150  }
151  root = root >> 1;
152  place = place >> 2;
153  }
154  return root;
155 }
156 
157 
158 //http://www.codecodex.com/wiki/Calculate_an_integer_square_root
159 uint16_t // OR uint16_t OR uint8_t
160 isqrt16 (uint16_t n) // OR isqrt16 ( uint16_t n ) OR isqrt8 ( uint8_t n ) - respectively [ OR overloaded as isqrt (uint16_t?? n) in C++ ]
161 {
162  uint16_t // OR register uint16_t OR register uint8_t - respectively
163  root, remainder, place;
164 
165  root = 0;
166  remainder = n;
167  place = 0x4000; // OR place = 0x4000; OR place = 0x40; - respectively
168 
169  while (place > remainder)
170  place = place >> 2;
171  while (place)
172  {
173  if (remainder >= root + place)
174  {
175  remainder = remainder - root - place;
176  root = root + (place << 1);
177  }
178  root = root >> 1;
179  place = place >> 2;
180  }
181  return root;
182 }
183 
184 
185 /** @} */