Mozzi  version v2.0
sound synthesis library for Arduino
mozzi_fixmath.h
1 /*
2  * mozzi_fixmath.h
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 #ifndef FIXEDMATH_H_
13 #define FIXEDMATH_H_
14 
15 #include <Arduino.h>
16 
17 /** @defgroup fixmath Fast integer based fixed-point arithmetic
18 
19 @note For new sketches it is recommended to utitlize the FixMath library with its typesafe classes UFix and SFix, instead of these
20  typedefs! See https://github.com/tomcombriat/FixMath . These are provided for backwards compatibility, only.
21 
22 Fixed point fractional number types and conversion routines. Fixed point is often best for fast audio code for Arduino, and these can ease some of the pain. </p><dl class="section note"><dt>Note</dt><dd>Take care when converting that the important bits of your numbers will fit in the types you choose!
23 
24 Timing: converting between fixed and float 10-12us, converting between fixed types about 1us.
25 */
26 
27 /** @ingroup fixmath
28 @{
29 */
30 // types
31 typedef int8_t Q0n7; /**< signed fractional number using 7 fractional bits, represents -0.5 to 0.496*/
32 typedef int8_t Q7n0; /**< ordinary old signed Q7n0 int8_t with 0 fractional bits, represents -128 to 127*/
33 typedef uint8_t Q0n8; /**< unsigned fractional number using 8 fractional bits, represents 0.0 to 0.996*/
34 typedef uint8_t Q8n0; /**< normal uint8_t with 0 fractional bits, represents 0.0 to 255.0*/
35 typedef uint16_t Q0n16; /**< unsigned fractional number using 16 fractional bits, represents 0.0 to 0.999*/
36 typedef uint32_t Q0n31; /**< signed number using 0 integer bits and 31 fractional bits, represents -0.2147483648 to 0.2147483647*/
37 typedef int16_t Q7n8; /**< signed fractional number using 7 integer bits and 8 fractional bits, represents -127.996 to 127.996*/
38 typedef uint16_t Q3n13; /**< unsigned fractional number using 3 integer bits and 13 fractional bits, represents 0 to 7.999*/
39 typedef int16_t Q1n14; /**< signed fractional number using 1 integer bit and 14 fractional bits, represents -1.999 to 1.999*/
40 typedef int16_t Q15n0; /**< signed number using 15 integer bits and 0 fractional bits, represents -32768 to 32767*/
41 typedef uint16_t Q8n8; /**< unsigned fractional number using 8 integer bits and 8 fractional bits, represents 0 to 255.996*/
42 typedef int16_t Q0n15; /**< signed fractional number using 0 integer bits and 15 fractional bits, represents -0.32768 to 0.32767*/
43 typedef uint16_t Q1n15; /**< unsigned fractional number using 1 integer bit and 15 fractional bits, represents 0 to 1.999*/
44 typedef uint16_t Q16n0; /**< unsigned number using 16 integer bits and 0 fractional bits, represents 0 to 65536.0*/
45 typedef int32_t Q23n8; /**< signed fractional number using 23 integer bits and 8 fractional bits, represents -8388607.996 to 8388607.996*/
46 typedef int32_t Q15n16; /**< signed fractional number using 15 integer bits and 16 fractional bits, represents -32767.999 to 32767.999*/
47 typedef int32_t Q31n0; /**< signed (normal int32_t int16_t) number using 31 integer bits and 0 fractional bits, represents -2147483648 to 2147483647*/
48 typedef uint32_t Q32n0; /**< unsigned (normal uint32_t int16_t) number using 32 integer bits and 0 fractional bits, represents 0 to 4294967295*/
49 typedef uint32_t Q0n32; /**< unsigned fractional number using 0 integer bits and 32 fractional bits, represents 0 to 0.999999999767169*/
50 typedef uint32_t Q8n24; /**< signed fractional number using 8 integer bits and 24 fractional bits, represents 0 to 255.999*/
51 typedef uint32_t Q24n8; /**< unsigned fractional number using 24 integer bits and 8 fractional bits, represents 0 to 16777215*/
52 typedef uint32_t Q16n16; /**< unsigned fractional number using 16 integer bits and 16 fractional bits, represents 0 to 65535.999*/
53 /** @}*/
54 
55 /** @ingroup fixmath
56 @{
57 */
58 // macros to save runtime calculations for representations of 1
59 #define Q0n7_FIX1 ((Q0n7) 127) /**< 0.992 in Q0n7 format*/
60 #define Q7n8_FIX1 ((Q7n8) 256) /**< 1 in Q7n8 format*/
61 #define Q8n8_FIX1 ((Q8n8) 256) /**< 1 in Q8n8 format*/
62 #define Q23n8_FIX1 ((Q23n8) 256) /**< 1 in Q23n8 format*/
63 #define Q1n14_FIX1 ((Q1n14) 16384) /**< 1 in Q1n14 format*/
64 #define Q1n15_FIX1 ((Q1n15) 32768) /**< 1 in Q1n15 format*/
65 #define Q16n16_FIX1 ((Q16n16) 65536) /**< 1 in Q16n16 format*/
66 #define Q0n15_FIX1 ((Q0n15) 32767) /**< 0.999 in Q0n15 format*/
67 #define Q0n16_FIX1 ((Q0n16) 65535) /**< 0.999 in Q0n16 format*/
68 #define Q15n0_FIX1 ((Q15n0) 16384) /**< 1 in Q15n0 format*/
69 #define Q15n16_FIX1 ((Q15n16) 65536) /**< 1 in Q15n16 format*/
70 #define Q8n24_FIX1 ((Q8n24) 16777216) /**< 1 in Q8n24 format*/
71 #define Q0n32_FIX1 ((Q0n32) 4294967295) /**< 0.999999999767169 in Q0n32 format*/
72 
73 #define Q16n16_PI ((Q16n16) 205887) /**< PI in Q16n16 format*/
74 #define Q3n13_2PI ((Q3n13) 411775) /**< 2*PI in Q3n13 format*/
75 #define Q16n16_2PI ((Q16n16) 411775) /**< 2*PI in Q16n16 format*/
76 
77 #define low15bits ((Q1n15) 32767) /**< Useful for keeping the lower 15 bits of a Q1n15 number, using &*/
78 /** @}*/
79 
80 
81 /*
82 Type conversions: Float to Q
83 
84 To convert a number from floating point to Qm.n format:
85 
86  Multiply the floating point number by 2^n
87  Round to the nearest integer
88 
89 Q to float
90 
91 To convert a number from Qm.n format to floating point:
92 
93  Convert the number to floating point as if it were an integer
94  Multiply by 2^-n
95 */
96 /** @ingroup fixmath
97 @{
98 */
99 inline
100 Q0n7 float_to_Q0n7(float a) { return static_cast<Q0n7>(a*256); } /**<Convert float to Q0n7 fix. @param a is a float*/
101 
102 inline
103 Q0n8 float_to_Q0n8(float a) { return static_cast<Q0n8>(a*256); } /**<Convert float to Q0n8 fix. @param a is a float*/
104 
105 inline
106 Q7n8 float_to_Q7n8(float a) { return static_cast<Q7n8>(a*256); } /**<Convert float to Q7n8 fix. @param a is a float*/
107 
108 inline
109 Q8n8 float_to_Q8n8(float a) { return static_cast<Q8n8>(a*256); } /**<Convert float to Q8n8 fix. @param a is a float*/
110 
111 inline
112 Q1n14 float_to_Q1n14(float a) { return static_cast<Q1n14>(a*16384); } /**<Convert float to Q1n14 fix. @param a is a float*/
113 
114 inline
115 Q1n15 float_to_Q1n15(float a) { return static_cast<Q1n15>(a*32768); } /**<Convert float to Q1n15 fix. @param a is a float*/
116 
117 inline
118 Q8n24 float_to_Q8n24(float a) { return static_cast<Q8n24>(a*16777216); } /**<Convert float to Q8n24 fix. @param a is a float*/
119 
120 inline
121 Q23n8 float_to_Q23n8(float a) { return static_cast<Q23n8>(a*256); } /**<Convert float to Q23n8 fix. @param a is a float*/
122 
123 inline
124 Q24n8 float_to_Q24n8(float a) { return static_cast<Q24n8>(a*256); } /**<Convert float to Q24n8 fix. @param a is a float*/
125 
126 inline
127 Q16n16 float_to_Q16n16(float a) { return static_cast<Q16n16>(a*65536); } /**<Convert float to Q16n16 fix. @param a is a float*/
128 
129 inline
130 Q0n16 float_to_Q0n16(float a) { return static_cast<Q0n16>(a*65536); } /**<Convert float to Q0n16 fix. @param a is a float*/
131 
132 inline
133 Q15n16 float_to_Q15n16(float a) { return static_cast<Q15n16>(a*65536); } /**<Convert float to Q15n16 fix. @param a is a float*/
134 
135 inline
136 Q1n14 Q0n7_to_Q1n14(Q0n7 a) { return (static_cast<Q1n14>(a))<<7; } /**<Convert Q0n7 int8_t to Q1n14 fix. @param a is a Q0n7 int8_t */
137 
138 inline
139 Q15n16 Q0n7_to_Q15n16(Q0n7 a) { return (static_cast<Q15n16>(a))<<8; } /**<Convert Q0n7 signed int8_t to Q15n16 fix. @param a is a Q0n7 signed int8_t */
140 
141 inline
142 float Q0n7_to_float(Q0n7 a) { return (static_cast<float>(a))/256; } /**<Convert Q0n7 fix to float. @param a is a Q0n7 int8_t*/
143 
144 inline
145 Q1n15 Q0n8_to_Q1n15(Q0n8 a) { return (static_cast<Q1n15>(a))<<7; } /**<Convert Q0n8 uint8_t to Q1n15 fix. @param a is a Q0n8 uint8_t */
146 
147 inline
148 Q8n8 Q0n8_to_Q8n8(Q0n8 a) { return (static_cast<Q8n8>(a))<<8; } /**<Convert Q0n8 uint8_t to Q8n8 fix. @param a is a Q0n8 uint8_t */
149 
150 inline
151 Q8n24 Q0n8_to_Q8n24(Q0n8 a) { return (static_cast<Q8n24>(a))<<16; } /**<Convert Q0n8 uint8_t to Q8n24 fix. @param a is a Q0n8 uint8_t */
152 
153 inline
154 Q24n8 Q0n8_to_Q24n8(Q0n8 a) { return (static_cast<Q24n8>(a))<<8; } /**<Convert Q0n8 uint8_t to Q24n8 fix. @param a is a Q0n8 uint8_t */
155 
156 inline
157 Q15n16 Q0n8_to_Q15n16(Q0n8 a) { return (static_cast<Q15n16>(a))<<8; } /**<Convert Q0n8 uint8_t to Q15n16 fix. @param a is a Q0n8 uint8_t */
158 
159 inline
160 Q16n16 Q0n8_to_Q16n16(Q0n8 a) { return (static_cast<Q16n16>(a))<<8; } /**<Convert Q0n8 uint8_t to Q16n16 fix. @param a is a Q0n8 uint8_t */
161 
162 inline
163 float Q0n8_to_float(Q0n8 a) { return (static_cast<float>(a))/256; } /**<Convert Q0n8 fix to float. @param a is a Q0n8 uint8_t*/
164 
165 inline
166 Q7n8 Q7n0_to_Q7n8(Q7n0 a) { return (static_cast<Q7n8>(a))<<8; } /**<Convert Q7n0 int8_t to Q7n8 fix. @param a is a int8_t*/
167 
168 inline
169 Q15n16 Q7n0_to_Q15n16(Q7n0 a) { return (static_cast<Q15n16>(a))<<16; } /**<Convert Q7n0 int8_t to Q15n16 fix. @param a is a int8_t*/
170 
171 inline
172 Q7n8 Q8n0_to_Q7n8(Q8n0 a) { return (static_cast<Q7n8>(a))<<8; } /**<Convert Q8n0 uint8_t to Q7n8 fix. @param a is a Q8n0 uint8_t*. Beware of overflow. */
173 
174 inline
175 Q8n8 Q8n0_to_Q8n8(Q8n0 a) { return (static_cast<Q8n8>(a))<<8; } /**<Convert uint8_t to Q8n8 fix. @param a is a Q8n0 uint8_t*/
176 
177 inline
178 Q15n16 Q8n0_to_Q15n16(Q8n0 a) { return (static_cast<Q15n16>(a))<<16; } /**<Convert Q8n0 uint8_t to Q15n16 fix. @param a is a Q8n0 uint8_t */
179 
180 inline
181 Q16n16 Q8n0_to_Q16n16(Q8n0 a) { return (static_cast<Q16n16>(a))<<16; } /**<Convert Q8n0 uint8_t to Q16n16 fix. @param a is a Q8n0 uint8_t */
182 
183 inline
184 Q7n0 Q7n8_to_Q7n0(Q7n8 a) { return static_cast<Q7n0>((Q7n8)a>>8); } /**<Convert Q7n8 fix to Q7n0. @param a is a Q7n8 int16_t*/
185 
186 inline
187 Q15n16 Q7n8_to_Q15n16(Q7n8 a) { return (static_cast<Q15n16>(a))<<8; } /**<Convert Q7n8 fix to Q15n16. @param a is a Q7n8 int16_t*/
188 
189 inline
190 float Q7n8_to_float(Q7n8 a) { return (static_cast<float>(a))/256; } /**<Convert Q7n8 fix to float. @param a is a Q7n8 int16_t*/
191 
192 inline
193 Q8n0 Q8n8_to_Q8n0(Q8n8 a) { return static_cast<Q8n0>((Q8n8)a>>8); } /**<Convert Q8n8 fix to Q8n0 uint8_t. @param a is a Q8n8 uint16_t*/
194 
195 inline
196 Q16n16 Q8n8_to_Q16n16(Q8n8 a) { return (static_cast<Q16n16>(a))<<8; } /**<Convert Q8n8 fix to Q16n16 uint32_t. @param a is a Q8n8 uint16_t*/
197 
198 inline
199 float Q8n8_to_float(Q8n8 a) { return (static_cast<float>(a))/256; } /**<Convert Q8n8 fix to float. @param a is a Q8n8 uint16_t*/
200 
201 inline
202 Q0n7 Q1n14_to_Q0n7(Q1n14 a) { return static_cast<Q0n7>((Q1n14)a>>7); } /**<Convert Q1n14 fixed to Q0n7 int8_t. @param a is a Q1n14 int16_t*/
203 
204 inline
205 float Q1n14_to_float(Q1n14 a) { return (static_cast<float>(a))/16384; } /**<Convert fix to float. @param a is an int16_t*/
206 
207 inline
208 Q0n8 Q1n15_to_Q0n8(Q1n15 a) { return static_cast<Q0n8>((Q1n15)a>>7); } /**<Convert Q1n15 fixed to Q0n8 uint8_t. Only for positive values! @param a is a Q1n15 uint16_t*/
209 
210 inline
211 float Q1n15_to_float(Q1n15 a) { return (static_cast<float>(a))/32768; } /**<Convert fix to float. @param a is a Q1n15 uint16_t*/
212 
213 inline
214 float Q0n16_to_float(Q0n16 a) { return (static_cast<float>(a))/65536; } /**<Convert fix to float. @param a is a Q0n16 uint16_t*/
215 
216 inline
217 Q15n16 Q15n0_to_Q15n16(Q15n0 a) { return (static_cast<Q15n16>(a))<<16; } /**<Convert Q15n0 int16_t to Q15n16 fix. @param a is a Q15n0 int16_t */
218 
219 inline
220 Q15n16 Q16n0_to_Q15n16(Q16n0 a) { return (static_cast<Q15n16>(a))<<16; } /**<Convert Q16n0 uint16_t to Q15n16 fix. @param a is a Q16n0 uint16_t */
221 
222 inline
223 Q23n8 Q16n0_to_Q23n8(Q16n0 a) { return (static_cast<Q23n8>(a))<<8; } /**<Convert Q16n0 uint16_t to Q23n8 fixed point signed int32_t. @param a is a Q16n0 uint16_t*/
224 
225 inline
226 Q24n8 Q16n0_to_Q24n8(Q16n0 a) { return (static_cast<Q24n8>(a))<<8; } /**<Convert Q16n0 uint16_t to Q24n8 fixed point uint32_t. @param a is a Q16n0 uint16_t*/
227 
228 inline
229 Q16n16 Q16n0_to_Q16n16(Q16n0 a) { return (static_cast<Q16n16>(a))<<16; } /**<Convert Q16n0 uint16_t to Q16n16 fixed point uint32_t. @param a is a Q16n0 uint16_t*/
230 
231 inline
232 float Q16n0_to_float(Q16n0 a) { return (static_cast<float>(a)); } /**<Convert Q16n0 uint16_t to float. @param a is a Q16n0 uint16_t*/
233 
234 inline
235 Q0n8 Q8n24_to_Q0n8(Q8n24 a) { return static_cast<Q0n8>((Q8n24)a>>16); } /**<Convert Q8n24 fixed to Q0n8 uint8_t. @param a is a Q8n24 uint32_t*/
236 
237 inline
238 float Q8n24_to_float(Q8n24 a) { return (static_cast<float>(a))/16777216; } /**<Convert fix to float. @param a is a Q8n24 uint32_t*/
239 
240 
241 inline
242 Q31n0 Q23n8_to_Q31n0(Q23n8 a) { return static_cast<Q31n0>((Q23n8)a>>8); } /**<Convert Q23n8 fixed to Q31n0 int32_t. @param a is a Q23n8 int32_t*/
243 
244 inline
245 Q16n0 Q23n8_to_Q16n0(Q23n8 a) { return static_cast<Q16n0>((Q23n8)a>>8); } /**<Convert Q23n8 fixed to Q16n0 uint16_t. Positive values only. @param a is a Q23n8 int32_t*/
246 
247 inline
248 Q15n0 Q23n8_to_Q15n0(Q23n8 a) { return static_cast<Q15n0>((Q23n8)a>>8); } /**<Convert Q23n8 fixed to Q15n0 signed int16_t. @param a is a Q23n8 int32_t*/
249 
250 inline
251 Q7n8 Q23n8_to_Q7n8(Q23n8 a) { return static_cast<Q7n8>(a); } /**<Convert Q23n8 fixed to Q7n8 signed int16_t, losing most significant bits. @param a is a Q23n8 signed int32_t.*/
252 
253 
254 inline
255 float Q23n8_to_float(Q23n8 a) { return (static_cast<float>(a))/256; } /**<Convert fix to float. @param a is a Q23n8 signed int32_t*/
256 
257 inline
258 Q0n8 Q24n8_to_Q0n8(Q24n8 a) { return static_cast<Q0n8>(a); } /**<Convert Q24n8 fixed to Q0n8 uint8_t. @param a is a Q24n8 uint32_t*/
259 
260 inline
261 Q16n16 Q24n8_to_Q16n0(Q24n8 a) { return (static_cast<Q16n0>((Q24n8)a))>>8; } /**<Convert Q24n8 fixed to Q16n0 uint16_t. @param a is a Q24n8 uint32_t*/
262 
263 inline
264 Q32n0 Q24n8_to_Q32n0(Q24n8 a) { return static_cast<Q32n0>((Q24n8)a>>8); } /**<Convert Q24n8 fixed to Q32n0 uint32_t. @param a is a Q24n8 uint32_t*/
265 
266 inline
267 Q16n16 Q24n8_to_Q16n16(Q24n8 a) { return (static_cast<Q16n16>(a))<<8; } /**<Convert Q24n8 fixed to Q16n16 uint32_t. @param a is a Q24n8 uint32_t*/
268 
269 inline
270 float Q24n8_to_float(Q24n8 a) { return (static_cast<float>(a))/256; } /**<Convert fix to float. @param a is a Q24n8 uint32_t*/
271 
272 inline
273 Q0n8 Q15n16_to_Q0n8(Q15n16 a) { return static_cast<Q0n8>((Q15n16)a>>8); } /**<Convert Q15n16 fixed to Q0n8 uint8_t. Only for positive values! @param a is a Q15n16 signed int32_t*/
274 
275 inline
276 Q8n0 Q15n16_to_Q8n0(Q15n16 a) { return static_cast<Q8n0>((Q15n16)a>>16); } /**<Convert Q15n16 fixed to Q8n0 uint8_t. Only for positive values! @param a is a Q15n16 signed int32_t*/
277 
278 inline
279 Q15n0 Q15n16_to_Q15n0(Q15n16 a) { return static_cast<Q15n0>((Q15n16)a>>16); } /**<Convert Q15n16 fixed to Q15n0 signed int16_t. @param a is a Q15n16 signed int32_t*/
280 
281 inline
282 Q7n8 Q15n16_to_Q7n8(Q15n16 a) { return static_cast<Q7n8>((Q15n16)a>>8); } /**<Convert Q15n16 fixed to Q7n8 signed int16_t, keeping middle bits only. @param a is a Q15n16 signed int32_t.*/
283 
284 inline
285 Q8n8 Q15n16_to_Q8n8(Q15n16 a) { return static_cast<Q8n8>((Q15n16)a>>8); } /**<Convert Q15n16 fixed to Q8n8 signed int16_t, keeping middle bits only. @param a is a Q15n16 signed int32_t.*/
286 
287 inline
288 Q23n8 Q15n16_to_Q23n8(Q15n16 a) { return static_cast<Q23n8>((Q15n16)a>>8); } /**<Convert Q15n16 fixed to Q23n8 signed int32_t. @param a is a Q15n16 signed int32_t.*/
289 
290 inline
291 float Q15n16_to_float(Q15n16 a) { return (static_cast<float>(a))/65536; } /**<Convert fix to float. @param a is a Q15n16 signed int32_t*/
292 
293 inline
294 Q0n8 Q16n16_to_Q0n8(Q16n16 a) { return static_cast<Q0n8>((Q16n16)a>>8); } /**<Convert Q16n16 fixed to Q0n8 uint8_t. @param a is a Q16n16 uint32_t*/
295 
296 inline
297 Q8n8 Q16n16_to_Q8n8(Q8n8 a) { return static_cast<Q8n8>((Q16n16)a>>16); } /**<Convert Q16n16 fixed to Q8n8 uint16_t. @param a is a Q16n16 uint32_t*/
298 
299 inline
300 Q16n0 Q16n16_to_Q16n0(Q16n16 a) { return static_cast<Q16n0>((Q16n16)a>>16); } /**<Convert Q16n16 fixed to Q16n0 uint16_t. @param a is a Q16n16 uint32_t*/
301 
302 inline
303 Q24n8 Q16n16_to_Q24n8(Q16n16 a) { return static_cast<Q24n8>((Q16n16)a>>8); } /**<Convert Q16n16 fixed to Q24n8 uint32_t. @param a is a Q16n16 uint32_t*/
304 
305 inline
306 float Q16n16_to_float(Q16n16 a) { return (static_cast<float>(a))/65536; } /**<Convert fix to float. @param a is a Q16n16 uint32_t*/
307 /** @}*/
308 
309 /* @ingroup fixmath
310 Fast (?) fixed point multiply for Q7n8 fractional numbers.
311 The c version below is 3 times faster, and not subject to the same overflow limitations (+-3.99, or +-2048)
312 @param a Q7n8 format multiplicand
313 @param b Q7n8 format multiplier
314 @return a Q7n8 format product
315 */
316 /*
317 #define Q7n8_mult(a,b) \
318 ({ \
319 int16_t prod, val1=a, val2=b ; \
320 __asm__ __volatile__ ( \
321  "muls %B1, %B2 \n\t" \
322  "mov %B0, r0 \n\t" \
323  "mul %A1, %A2\n\t" \
324  "mov %A0, r1 \n\t" \
325  "mulsu %B1, %A2 \n\t" \
326  "add %A0, r0 \n\t" \
327  "adc %B0, r1 \n\t" \
328  "mulsu %B2, %A1 \n\t" \
329  "add %A0, r0 \n\t" \
330  "adc %B0, r1 \n\t" \
331  "clr r1 \n\t" \
332  : "=&d" (prod) \
333  : "a" (val1), "a" (val2) \
334  ); \
335  prod; \
336 })
337 */
338 
339 /** @ingroup fixmath
340 Fast fixed point multiply for Q7n8 fractional numbers.
341 @param a Q7n8 format multiplicand
342 @param b Q7n8 format multiplier
343 @return a Q7n8 format product
344 */
345 inline
346 Q7n8 Q7n8_mult(Q7n8 a, Q7n8 b) {
347  return ((int16_t)((((int32_t)(a))*(b))>>8));
348 }
349 
350 
351 /*
352 #define FMULS8(v1, v2) \
353 ({ \
354  uint8_t res; \
355  uint8_t val1 = v1; \
356  uint8_t val2 = v2; \
357  __asm__ __volatile__ \
358  ( \
359  "fmuls $1, $2" "\n\t" \
360  "mov $0, r1" "\n\t" \
361  "clr r1" "\n\t" \
362  : "=&d" (res) \
363  : "a" (val1), "a" (val2) \
364  ); \
365  res; \
366 }) */
367 
368 
369 /*
370 // from octosynth, Joe Marshall 2011:
371 
372  // multiply 2 16 bit numbers together and shift 8 without precision loss
373  // requires assembler really
374  volatile uint8_t zeroReg=0;
375  volatile uint16_t multipliedCounter=oscillators[c].phaseStep;
376  asm volatile
377  (
378  // high uint8_ts mult together = high uint8_t
379  "ldi %A[outVal],0" "\n\t"
380  "mul %B[phaseStep],%B[pitchB}]" "\n\t"
381  "mov %B[outVal],r0" "\n\t"
382  // ignore overflow into r1 (should never overflow)
383  // low uint8_t * high uint8_t -> both uint8_ts
384  "mul %A[phaseStep],%B[pitchB}]" "\n\t"
385  "add %A[outVal],r0" "\n\t"
386  // carry into high uint8_t
387  "adc %B[outVal],r1" "\n\t"
388  // high uint8_t* low uint8_t -> both uint8_ts
389  "mul %B[phaseStep],%A[pitchB}]" "\n\t"
390  "add %A[outVal],r0" "\n\t"
391  // carry into high uint8_t
392  "adc %B[outVal],r1" "\n\t"
393  // low uint8_t * low uint8_t -> round
394  "mul %A[phaseStep],%A[pitchB}]" "\n\t"
395  // the adc below is to round up based on high bit of low*low:
396  "adc %A[outVal],r1" "\n\t"
397  "adc %B[outVal],%[ZERO]" "\n\t"
398  "clr r1" "\n\t"
399  :[outVal] "=&d" (multipliedCounter)
400  :[phaseStep] "d" (oscillators[c].phaseStep),[pitchB}] "d"( pitchB}Multiplier),[ZERO] "d" (zeroReg)
401  :"r1","r0"
402  );
403  oscillators[c].phaseStep=multipliedCounter;
404 
405  */
406 
407 
408 
409 int16_t ipow(int16_t base, int16_t exp); /**< dangerous overflow-prone int16_t power function */
410 
411 Q16n16 Q16n16_pow2(Q8n8 exponent);
412 
415 uint8_t uint8_tRnd(uint8_t min, uint8_t max);
416 uint16_t isqrt16(uint16_t n);
417 uint32_t isqrt32(uint32_t n);
418 
419 #endif /* FIXEDMATH_H_ */