/[svn]/linuxsampler/trunk/src/common/RTMath.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/RTMath.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2931 - (show annotations) (download) (as text)
Sat Jul 9 14:38:33 2016 UTC (7 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 14204 byte(s)
* Implemented built-in instrument script function "change_vol()".
* Implemented built-in instrument script function "change_tune()".
* Implemented built-in instrument script function "change_pan()".
* Bumped version (2.0.0.svn11).

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2016 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __RT_MATH_H__
25 #define __RT_MATH_H__
26
27 #include <math.h>
28 #include <stdint.h>
29 #include "global_private.h"
30
31 /// Needed for calculating frequency ratio used to pitch a sample
32 #define TWELVEHUNDREDTH_ROOT_OF_TWO 1.000577789506555
33
34 enum implementation_t {
35 CPP,
36 ASM_X86_MMX_SSE
37 };
38
39 /** @brief Real Time Math Base Class
40 *
41 * Math functions for real time operation. This base class contains all
42 * non-template methods.
43 */
44 class RTMathBase {
45 public:
46 /**
47 * Highly accurate time stamp.
48 */
49 typedef uint32_t time_stamp_t;
50
51 /**
52 * We read the processor's cycle count register as a reference
53 * for the real time. These are of course only abstract values
54 * with arbitrary time entity, but that's not a problem as long
55 * as we calculate relatively.
56 */
57 static time_stamp_t CreateTimeStamp();
58
59 /**
60 * Calculates the frequency ratio for a pitch value given in cents
61 * (assuming equal tempered scale of course, divided into 12
62 * semitones per octave and 100 cents per semitone).
63 *
64 * Note: CONFIG_MAX_PITCH (defined in config.h) has to be defined to an
65 * appropriate value, otherwise the behavior of this function is
66 * undefined, but most probably if CONFIG_MAX_PITCH is too small, the
67 * application will crash due to segmentation fault here.
68 *
69 * @param cents - pitch value in cents (+1200 cents means +1 octave)
70 * @returns frequency ratio (e.g. +2.0 for +1 octave)
71 */
72 inline static double CentsToFreqRatio(double Cents) {
73 int index_int = (int) (Cents); // integer index
74 float index_fract = Cents - index_int; // fractional part of index
75 return pCentsToFreqTable[index_int] + index_fract * (pCentsToFreqTable[index_int+1] - pCentsToFreqTable[index_int]);
76 }
77
78 /**
79 * Slower version of CentsToFreqRatio, for big values.
80 *
81 * @param cents - pitch value in cents (+1200 cents means +1 octave)
82 * @returns frequency ratio (e.g. +2.0 for +1 octave)
83 */
84 static double CentsToFreqRatioUnlimited(double Cents) {
85 int octaves = int(Cents / 1200);
86 double x = CentsToFreqRatio(Cents - octaves * 1200);
87 return octaves < 0 ? x / (1 << -octaves) : x * (1 << octaves);
88 }
89
90 /**
91 * Inverse function to CentsToFreqRatio(). This function is a bit
92 * slow, so it should not be called too frequently.
93 */
94 static double FreqRatioToCents(double FreqRatio) {
95 return log(FreqRatio) / log(TWELVEHUNDREDTH_ROOT_OF_TWO);
96 }
97
98 /**
99 * Calculates the line ratio value representation (linear scale)
100 * of the @a decibel value provided (exponential scale).
101 *
102 * The context of audio acoustic sound pressure levels is assumed, and
103 * hence the field version of the dB unit is used here (which uses a
104 * linear factor of 20). This function is a bit slow, so it should
105 * not be called too frequently.
106 *
107 * @param decibel - sound pressure level in dB
108 * @returns linear ratio of the supplied dB value
109 */
110 static float DecibelToLinRatio(float decibel) {
111 return powf(10.f, decibel / 20.f);
112 }
113
114 /**
115 * Calculates the relatively summed average of a set of values.
116 *
117 * @param current - the current avaerage value of all previously summed values
118 * @param sample - new value to be applied as summed average to the existing values
119 * @param n - amount of sample values applied so far
120 * @returns new average value of all summed values (including the new @a sample)
121 */
122 inline static float RelativeSummedAvg(float current, float sample, int n) {
123 return current + (sample - current) / float(n);
124 }
125
126 private:
127 static float* pCentsToFreqTable;
128
129 static float* InitCentsToFreqTable();
130 };
131
132 /** @brief Real Time Math
133 *
134 * This is a template which provides customized methods for the desired low
135 * level implementation. The ASM_X86_MMX_SSE implementation of each method
136 * for example doesn't use 387 FPU instruction. This is needed for MMX
137 * algorithms which do not allow mixed MMX and 387 instructions.
138 */
139 template<implementation_t IMPL = CPP>
140 class __RTMath : public RTMathBase {
141 public:
142 // conversion using truncate
143 inline static int Int(const float a) {
144 switch (IMPL) {
145 #if CONFIG_ASM && ARCH_X86
146 case ASM_X86_MMX_SSE: {
147 int ret;
148 asm (
149 "cvttss2si %1, %0 # convert to int\n\t"
150 : "=r" (ret)
151 : "m" (a)
152 );
153 return ret;
154 }
155 #endif // CONFIG_ASM && ARCH_X86
156 default: {
157 return (int) a;
158 }
159 }
160 }
161
162 //for doubles and everything else except floats
163 template<class T_a> inline static int Int(const T_a a) {
164 return (int) a;
165 }
166
167 inline static float Float(const int a) {
168 switch (IMPL) {
169 #if CONFIG_ASM && ARCH_X86
170 case ASM_X86_MMX_SSE: {
171 float ret;
172 asm (
173 "cvtsi2ss %1, %%xmm0 # convert to float\n\t"
174 "movss %%xmm0,%0 # output\n\t"
175 : "=m" (ret)
176 : "r" (a)
177 );
178 return ret;
179 }
180 #endif // CONFIG_ASM && ARCH_X86
181 default: {
182 return (float) a;
183 }
184 }
185 }
186
187 #if 0
188 //for everything except ints
189 template<class T_a> inline static float Float(T_a a) {
190 return (float) a;
191 }
192 #endif
193
194 inline static float Sum(const float& a, const float& b) {
195 switch (IMPL) {
196 #if CONFIG_ASM && ARCH_X86
197 case ASM_X86_MMX_SSE: {
198 float ret;
199 asm (
200 "movss %1, %%xmm0 # load a\n\t"
201 "addss %2, %%xmm0 # a + b\n\t"
202 "movss %%xmm0, %0 # output\n\t"
203 : "=m" (ret)
204 : "m" (a), "m" (b)
205 );
206 return ret;
207 }
208 #endif // CONFIG_ASM && ARCH_X86
209 default: {
210 return (a + b);
211 }
212 }
213 }
214
215 template<class T_a, class T_b> inline static T_a Sum(const T_a a, const T_b b) {
216 return (a + b);
217 }
218
219 inline static float Sub(const float& a, const float& b) {
220 switch (IMPL) {
221 #if CONFIG_ASM && ARCH_X86
222 case ASM_X86_MMX_SSE: {
223 float ret;
224 asm (
225 "movss %1, %%xmm0 # load a\n\t"
226 "subss %2, %%xmm0 # a - b\n\t"
227 "movss %%xmm0, %0 # output\n\t"
228 : "=m" (ret)
229 : "m" (a), "m" (b)
230 );
231 return ret;
232 }
233 #endif // CONFIG_ASM && ARCH_X86
234 default: {
235 return (a - b);
236 }
237 }
238 }
239
240 template<class T_a, class T_b> inline static T_a Sub(const T_a a, const T_b b) {
241 return (a - b);
242 }
243
244 inline static float Mul(const float a, const float b) {
245 switch (IMPL) {
246 #if CONFIG_ASM && ARCH_X86
247 case ASM_X86_MMX_SSE: {
248 float ret;
249 asm (
250 "movss %1, %%xmm0 # load a\n\t"
251 "mulss %2, %%xmm0 # a * b\n\t"
252 "movss %%xmm0, %0 # output\n\t"
253 : "=m" (ret)
254 : "m" (a), "m" (b)
255 );
256 return ret;
257 }
258 #endif // CONFIG_ASM && ARCH_X86
259 default: {
260 return (a * b);
261 }
262 }
263 }
264
265 template<class T_a, class T_b> inline static T_a Mul(const T_a a, const T_b b) {
266 return (a * b);
267 }
268
269 inline static float Div(const float a, const float b) {
270 switch (IMPL) {
271 #if CONFIG_ASM && ARCH_X86
272 case ASM_X86_MMX_SSE: {
273 float ret;
274 asm (
275 "movss %1, %%xmm0 # load a\n\t"
276 "divss %2, %%xmm0 # a / b\n\t"
277 "movss %%xmm0, %0 # output\n\t"
278 : "=m" (ret)
279 : "m" (a), "m" (b)
280 );
281 return ret;
282 }
283 #endif // CONFIG_ASM && ARCH_X86
284 default: {
285 return (a / b);
286 }
287 }
288 }
289
290 template<class T_a, class T_b> inline static T_a Div(const T_a a, const T_b b) {
291 return (a / b);
292 }
293
294 inline static float Min(const float a, const float b) {
295 switch (IMPL) {
296 #if CONFIG_ASM && ARCH_X86
297 case ASM_X86_MMX_SSE: {
298 float ret;
299 asm (
300 "movss %1, %%xmm0 # load a\n\t"
301 "minss %2, %%xmm0 # Minimum(a, b)\n\t"
302 "movss %%xmm0, %0 # output\n\t"
303 : "=m" (ret)
304 : "m" (a), "m" (b)
305 );
306 return ret;
307 }
308 #endif // CONFIG_ASM && ARCH_X86
309 default: {
310 return std::min(a, b);
311 }
312 }
313 }
314
315 template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
316 return (b < a) ? b : a;
317 }
318
319 inline static float Max(const float a, const float b) {
320 switch (IMPL) {
321 #if CONFIG_ASM && ARCH_X86
322 case ASM_X86_MMX_SSE: {
323 float ret;
324 asm (
325 "movss %1, %%xmm0 # load a\n\t"
326 "maxss %2, %%xmm0 # Maximum(a, b)\n\t"
327 "movss %%xmm0, %0 # output\n\t"
328 : "=m" (ret)
329 : "m" (a), "m" (b)
330 );
331 return ret;
332 }
333 #endif // CONFIG_ASM && ARCH_X86
334 default: {
335 return std::max(a, b);
336 }
337 }
338 }
339
340 template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
341 return (b > a) ? b : a;
342 }
343
344 inline static float Fmodf(const float &a, const float &b) {
345 switch (IMPL) {
346 #if CONFIG_ASM && ARCH_X86
347 case ASM_X86_MMX_SSE: {
348 float ret;
349 asm (
350 "movss %1, %%xmm0 # load a\n\t"
351 "movss %2, %%xmm1 # load b\n\t"
352 "movss %%xmm0,%%xmm2\n\t"
353 "divss %%xmm1, %%xmm2 # xmm2 = a / b\n\t"
354 "cvttss2si %%xmm2, %%ecx #convert to int\n\t"
355 "cvtsi2ss %%ecx, %%xmm2 #convert back to float\n\t"
356 "mulss %%xmm1, %%xmm2 # xmm2 = b * int(a/b)\n\t"
357 "subss %%xmm2, %%xmm0 #sub a\n\t"
358 "movss %%xmm0, %0 # output\n\t"
359 : "=m" (ret)
360 : "m" (a), "m" (b)
361 : "%ecx"
362 );
363 return ret;
364 }
365 #endif // CONFIG_ASM && ARCH_X86
366 default: {
367 return fmodf(a, b);
368 }
369 }
370 }
371 };
372
373 /// convenience typedef for using the default implementation (which is CPP)
374 typedef __RTMath<> RTMath;
375
376 #endif // __RT_MATH_H__

  ViewVC Help
Powered by ViewVC