/[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 2931 - (hide annotations) (download) (as text)
Sat Jul 9 14:38:33 2016 UTC (7 years, 9 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 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 328 * 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 schoenebeck 53 * 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 schoenebeck 554 * Note: CONFIG_MAX_PITCH (defined in config.h) has to be defined to an
65 schoenebeck 53 * appropriate value, otherwise the behavior of this function is
66 schoenebeck 554 * undefined, but most probably if CONFIG_MAX_PITCH is too small, the
67 schoenebeck 53 * 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 schoenebeck 319 int index_int = (int) (Cents); // integer index
74 schoenebeck 53 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 schoenebeck 829 /**
79 persson 1862 * 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 schoenebeck 829 * 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 schoenebeck 2931 /**
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 schoenebeck 319 private:
127     static float* pCentsToFreqTable;
128    
129     static float* InitCentsToFreqTable();
130     };
131    
132 schoenebeck 563 /** @brief Real Time Math
133 schoenebeck 319 *
134 schoenebeck 563 * 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 schoenebeck 319 */
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
146 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
156 persson 685 default: {
157     return (int) a;
158     }
159 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
170 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
181 persson 685 default: {
182     return (float) a;
183     }
184 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
197 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
209 persson 685 default: {
210     return (a + b);
211     }
212 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
222 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
234 persson 685 default: {
235     return (a - b);
236     }
237 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
247 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
259 persson 685 default: {
260     return (a * b);
261     }
262 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
272 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
284 persson 685 default: {
285     return (a / b);
286     }
287 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
297 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
309 persson 685 default: {
310 wylder 818 return std::min(a, b);
311 persson 685 }
312 schoenebeck 319 }
313     }
314    
315     template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
316 schoenebeck 53 return (b < a) ? b : a;
317     }
318    
319 schoenebeck 319 inline static float Max(const float a, const float b) {
320     switch (IMPL) {
321 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
322 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
334 persson 685 default: {
335 wylder 818 return std::max(a, b);
336 persson 685 }
337 schoenebeck 319 }
338     }
339    
340     template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
341 schoenebeck 53 return (b > a) ? b : a;
342     }
343    
344 schoenebeck 319 inline static float Fmodf(const float &a, const float &b) {
345     switch (IMPL) {
346 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
347 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
366 persson 685 default: {
367     return fmodf(a, b);
368     }
369 schoenebeck 319 }
370     }
371 schoenebeck 53 };
372    
373 schoenebeck 319 /// convenience typedef for using the default implementation (which is CPP)
374     typedef __RTMath<> RTMath;
375    
376 schoenebeck 53 #endif // __RT_MATH_H__

  ViewVC Help
Powered by ViewVC