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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2942 - (hide annotations) (download) (as text)
Wed Jul 13 15:51:06 2016 UTC (3 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 16095 byte(s)
* NKSP: Implemented built-in script variable "$KSP_TIMER".
* NKSP: Implemented built-in script variable "$NKSP_REAL_TIMER".
* NKSP: Implemented built-in script variable "$NKSP_PERF_TIMER".
* NKSP: Implemented built-in script variable "$ENGINE_UPTIME".
* Bumped version (2.0.0.svn14).

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 2931 * Copyright (C) 2005 - 2016 Christian Schoenebeck *
7 schoenebeck 53 * *
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 schoenebeck 328 #include <stdint.h>
29 schoenebeck 1424 #include "global_private.h"
30 schoenebeck 53
31     /// Needed for calculating frequency ratio used to pitch a sample
32     #define TWELVEHUNDREDTH_ROOT_OF_TWO 1.000577789506555
33    
34 schoenebeck 319 enum implementation_t {
35 schoenebeck 361 CPP,
36     ASM_X86_MMX_SSE
37 schoenebeck 319 };
38    
39 schoenebeck 563 /** @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 schoenebeck 319 class RTMathBase {
45 schoenebeck 53 public:
46     /**
47 schoenebeck 2942 * High resolution time stamp.
48 schoenebeck 328 */
49     typedef uint32_t time_stamp_t;
50    
51 schoenebeck 2942 typedef uint64_t usecs_t;
52    
53 schoenebeck 328 /**
54     * We read the processor's cycle count register as a reference
55     * for the real time. These are of course only abstract values
56     * with arbitrary time entity, but that's not a problem as long
57     * as we calculate relatively.
58 schoenebeck 2942 *
59     * @see unsafeMicroSeconds()
60 schoenebeck 328 */
61     static time_stamp_t CreateTimeStamp();
62    
63     /**
64 schoenebeck 53 * Calculates the frequency ratio for a pitch value given in cents
65     * (assuming equal tempered scale of course, divided into 12
66     * semitones per octave and 100 cents per semitone).
67     *
68 schoenebeck 554 * Note: CONFIG_MAX_PITCH (defined in config.h) has to be defined to an
69 schoenebeck 53 * appropriate value, otherwise the behavior of this function is
70 schoenebeck 554 * undefined, but most probably if CONFIG_MAX_PITCH is too small, the
71 schoenebeck 53 * application will crash due to segmentation fault here.
72     *
73     * @param cents - pitch value in cents (+1200 cents means +1 octave)
74     * @returns frequency ratio (e.g. +2.0 for +1 octave)
75     */
76     inline static double CentsToFreqRatio(double Cents) {
77 schoenebeck 319 int index_int = (int) (Cents); // integer index
78 schoenebeck 53 float index_fract = Cents - index_int; // fractional part of index
79     return pCentsToFreqTable[index_int] + index_fract * (pCentsToFreqTable[index_int+1] - pCentsToFreqTable[index_int]);
80     }
81    
82 schoenebeck 829 /**
83 persson 1862 * Slower version of CentsToFreqRatio, for big values.
84     *
85     * @param cents - pitch value in cents (+1200 cents means +1 octave)
86     * @returns frequency ratio (e.g. +2.0 for +1 octave)
87     */
88     static double CentsToFreqRatioUnlimited(double Cents) {
89     int octaves = int(Cents / 1200);
90     double x = CentsToFreqRatio(Cents - octaves * 1200);
91     return octaves < 0 ? x / (1 << -octaves) : x * (1 << octaves);
92     }
93    
94     /**
95 schoenebeck 829 * Inverse function to CentsToFreqRatio(). This function is a bit
96     * slow, so it should not be called too frequently.
97     */
98     static double FreqRatioToCents(double FreqRatio) {
99     return log(FreqRatio) / log(TWELVEHUNDREDTH_ROOT_OF_TWO);
100     }
101    
102 schoenebeck 2931 /**
103     * Calculates the line ratio value representation (linear scale)
104     * of the @a decibel value provided (exponential scale).
105     *
106     * The context of audio acoustic sound pressure levels is assumed, and
107     * hence the field version of the dB unit is used here (which uses a
108     * linear factor of 20). This function is a bit slow, so it should
109     * not be called too frequently.
110     *
111     * @param decibel - sound pressure level in dB
112     * @returns linear ratio of the supplied dB value
113     */
114     static float DecibelToLinRatio(float decibel) {
115     return powf(10.f, decibel / 20.f);
116     }
117    
118     /**
119     * Calculates the relatively summed average of a set of values.
120     *
121     * @param current - the current avaerage value of all previously summed values
122     * @param sample - new value to be applied as summed average to the existing values
123     * @param n - amount of sample values applied so far
124     * @returns new average value of all summed values (including the new @a sample)
125     */
126     inline static float RelativeSummedAvg(float current, float sample, int n) {
127     return current + (sample - current) / float(n);
128     }
129    
130 schoenebeck 2942 /**
131     * Clock source to use for getting the current time.
132     */
133     enum clock_source_t {
134     real_clock, ///< Use this to measure time that passed in reality (no matter if process got suspended).
135     process_clock, ///< Use this to measure only the CPU execution time of the current process (if the process got suspended, the clock is paused as well).
136     thread_clock, ///< Use this to measure only the CPU execution time of the current thread (if the process got suspended or another thread is executed, the clock is paused as well).
137     };
138    
139     /**
140     * Returns a time stamp of the current time in microseconds (in
141     * probably real-time @b unsafe way). There is no guarantee about
142     * what the returned amount of microseconds relates to (i.e.
143     * microseconds since epoch, microseconds since system uptime, ...).
144     * So you should only use it to calculate time differences between
145     * values taken with this method.
146     *
147     * @b CAUTION: This method may not @b NOT be real-time safe! On some
148     * systems it could be RT safe, but there is no guarantee whatsoever!
149     * So this method should only be used for debugging, benchmarking and
150     * other developing purposes !
151     *
152     * For creating time stamps in real-time context, use
153     * CreateTimeStamp() instead.
154     *
155     * @param source - the actual clock to use for getting the current
156     * time, note that the various clock sources may not
157     * be implemented on all systems
158     * @returns time stamp in microseconds
159     *
160     * @see CreateTimeStamp()
161     */
162     static usecs_t unsafeMicroSeconds(clock_source_t source);
163    
164 schoenebeck 319 private:
165     static float* pCentsToFreqTable;
166    
167     static float* InitCentsToFreqTable();
168     };
169    
170 schoenebeck 563 /** @brief Real Time Math
171 schoenebeck 319 *
172 schoenebeck 563 * This is a template which provides customized methods for the desired low
173     * level implementation. The ASM_X86_MMX_SSE implementation of each method
174     * for example doesn't use 387 FPU instruction. This is needed for MMX
175     * algorithms which do not allow mixed MMX and 387 instructions.
176 schoenebeck 319 */
177     template<implementation_t IMPL = CPP>
178     class __RTMath : public RTMathBase {
179     public:
180     // conversion using truncate
181     inline static int Int(const float a) {
182     switch (IMPL) {
183 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
184 schoenebeck 319 case ASM_X86_MMX_SSE: {
185     int ret;
186     asm (
187     "cvttss2si %1, %0 # convert to int\n\t"
188     : "=r" (ret)
189     : "m" (a)
190     );
191     return ret;
192     }
193 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
194 persson 685 default: {
195     return (int) a;
196     }
197 schoenebeck 319 }
198     }
199    
200     //for doubles and everything else except floats
201     template<class T_a> inline static int Int(const T_a a) {
202     return (int) a;
203     }
204    
205     inline static float Float(const int a) {
206     switch (IMPL) {
207 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
208 schoenebeck 319 case ASM_X86_MMX_SSE: {
209     float ret;
210     asm (
211     "cvtsi2ss %1, %%xmm0 # convert to float\n\t"
212     "movss %%xmm0,%0 # output\n\t"
213     : "=m" (ret)
214     : "r" (a)
215     );
216     return ret;
217     }
218 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
219 persson 685 default: {
220     return (float) a;
221     }
222 schoenebeck 319 }
223     }
224    
225     #if 0
226     //for everything except ints
227     template<class T_a> inline static float Float(T_a a) {
228     return (float) a;
229     }
230     #endif
231    
232     inline static float Sum(const float& a, const float& b) {
233     switch (IMPL) {
234 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
235 schoenebeck 319 case ASM_X86_MMX_SSE: {
236     float ret;
237     asm (
238     "movss %1, %%xmm0 # load a\n\t"
239     "addss %2, %%xmm0 # a + b\n\t"
240     "movss %%xmm0, %0 # output\n\t"
241     : "=m" (ret)
242     : "m" (a), "m" (b)
243     );
244     return ret;
245     }
246 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
247 persson 685 default: {
248     return (a + b);
249     }
250 schoenebeck 319 }
251     }
252    
253     template<class T_a, class T_b> inline static T_a Sum(const T_a a, const T_b b) {
254     return (a + b);
255     }
256    
257     inline static float Sub(const float& a, const float& b) {
258     switch (IMPL) {
259 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
260 schoenebeck 319 case ASM_X86_MMX_SSE: {
261     float ret;
262     asm (
263     "movss %1, %%xmm0 # load a\n\t"
264     "subss %2, %%xmm0 # a - b\n\t"
265     "movss %%xmm0, %0 # output\n\t"
266     : "=m" (ret)
267     : "m" (a), "m" (b)
268     );
269     return ret;
270     }
271 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
272 persson 685 default: {
273     return (a - b);
274     }
275 schoenebeck 319 }
276     }
277    
278     template<class T_a, class T_b> inline static T_a Sub(const T_a a, const T_b b) {
279     return (a - b);
280     }
281    
282     inline static float Mul(const float a, const float b) {
283     switch (IMPL) {
284 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
285 schoenebeck 319 case ASM_X86_MMX_SSE: {
286     float ret;
287     asm (
288     "movss %1, %%xmm0 # load a\n\t"
289     "mulss %2, %%xmm0 # a * b\n\t"
290     "movss %%xmm0, %0 # output\n\t"
291     : "=m" (ret)
292     : "m" (a), "m" (b)
293     );
294     return ret;
295     }
296 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
297 persson 685 default: {
298     return (a * b);
299     }
300 schoenebeck 319 }
301     }
302    
303     template<class T_a, class T_b> inline static T_a Mul(const T_a a, const T_b b) {
304     return (a * b);
305     }
306    
307     inline static float Div(const float a, const float b) {
308     switch (IMPL) {
309 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
310 schoenebeck 319 case ASM_X86_MMX_SSE: {
311     float ret;
312     asm (
313     "movss %1, %%xmm0 # load a\n\t"
314     "divss %2, %%xmm0 # a / b\n\t"
315     "movss %%xmm0, %0 # output\n\t"
316     : "=m" (ret)
317     : "m" (a), "m" (b)
318     );
319     return ret;
320     }
321 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
322 persson 685 default: {
323     return (a / b);
324     }
325 schoenebeck 319 }
326     }
327    
328     template<class T_a, class T_b> inline static T_a Div(const T_a a, const T_b b) {
329     return (a / b);
330     }
331    
332     inline static float Min(const float a, const float b) {
333     switch (IMPL) {
334 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
335 schoenebeck 319 case ASM_X86_MMX_SSE: {
336     float ret;
337     asm (
338     "movss %1, %%xmm0 # load a\n\t"
339     "minss %2, %%xmm0 # Minimum(a, b)\n\t"
340     "movss %%xmm0, %0 # output\n\t"
341     : "=m" (ret)
342     : "m" (a), "m" (b)
343     );
344     return ret;
345     }
346 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
347 persson 685 default: {
348 wylder 818 return std::min(a, b);
349 persson 685 }
350 schoenebeck 319 }
351     }
352    
353     template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
354 schoenebeck 53 return (b < a) ? b : a;
355     }
356    
357 schoenebeck 319 inline static float Max(const float a, const float b) {
358     switch (IMPL) {
359 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
360 schoenebeck 319 case ASM_X86_MMX_SSE: {
361     float ret;
362     asm (
363     "movss %1, %%xmm0 # load a\n\t"
364     "maxss %2, %%xmm0 # Maximum(a, b)\n\t"
365     "movss %%xmm0, %0 # output\n\t"
366     : "=m" (ret)
367     : "m" (a), "m" (b)
368     );
369     return ret;
370     }
371 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
372 persson 685 default: {
373 wylder 818 return std::max(a, b);
374 persson 685 }
375 schoenebeck 319 }
376     }
377    
378     template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
379 schoenebeck 53 return (b > a) ? b : a;
380     }
381    
382 schoenebeck 319 inline static float Fmodf(const float &a, const float &b) {
383     switch (IMPL) {
384 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
385 schoenebeck 319 case ASM_X86_MMX_SSE: {
386     float ret;
387     asm (
388     "movss %1, %%xmm0 # load a\n\t"
389     "movss %2, %%xmm1 # load b\n\t"
390     "movss %%xmm0,%%xmm2\n\t"
391     "divss %%xmm1, %%xmm2 # xmm2 = a / b\n\t"
392     "cvttss2si %%xmm2, %%ecx #convert to int\n\t"
393     "cvtsi2ss %%ecx, %%xmm2 #convert back to float\n\t"
394     "mulss %%xmm1, %%xmm2 # xmm2 = b * int(a/b)\n\t"
395     "subss %%xmm2, %%xmm0 #sub a\n\t"
396     "movss %%xmm0, %0 # output\n\t"
397     : "=m" (ret)
398     : "m" (a), "m" (b)
399     : "%ecx"
400     );
401     return ret;
402     }
403 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
404 persson 685 default: {
405     return fmodf(a, b);
406     }
407 schoenebeck 319 }
408     }
409 schoenebeck 53 };
410    
411 schoenebeck 319 /// convenience typedef for using the default implementation (which is CPP)
412     typedef __RTMath<> RTMath;
413    
414 schoenebeck 53 #endif // __RT_MATH_H__

  ViewVC Help
Powered by ViewVC