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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 53 by schoenebeck, Mon Apr 26 17:15:51 2004 UTC revision 617 by schoenebeck, Wed Jun 8 21:00:06 2005 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck         *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005 Christian Schoenebeck                              *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 24  Line 25 
25  #define __RT_MATH_H__  #define __RT_MATH_H__
26    
27  #include <math.h>  #include <math.h>
28    #include <stdint.h>
29  #include "global.h"  #include "global.h"
30    
31  /// Needed for calculating frequency ratio used to pitch a sample  /// Needed for calculating frequency ratio used to pitch a sample
32  #define TWELVEHUNDREDTH_ROOT_OF_TWO     1.000577789506555  #define TWELVEHUNDREDTH_ROOT_OF_TWO     1.000577789506555
33    
34  /** Real Time Math  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.   * Math functions for real time operation. This base class contains all
42     * non-template methods.
43   */   */
44  class RTMath {  class RTMathBase {
45      public:      public:
46          /**          /**
47           * Converts a double to integer type.           * Highly accurate time stamp.
48           */           */
49          inline static int DoubleToInt(double f) {          typedef uint32_t time_stamp_t;
50              #if ARCH_X86  
51              int i;          /**
52              __asm__ ("fistl %0" : "=m"(i) : "st"(f - 0.5) );           * We read the processor's cycle count register as a reference
53              return i;           * for the real time. These are of course only abstract values
54              #else           * with arbitrary time entity, but that's not a problem as long
55              return (int) f;           * as we calculate relatively.
56              #endif // ARCH_X86           */
57          }          static time_stamp_t CreateTimeStamp();
58    
59          /**          /**
60           * Calculates the frequency ratio for a pitch value given in cents           * Calculates the frequency ratio for a pitch value given in cents
61           * (assuming equal tempered scale of course, divided into 12           * (assuming equal tempered scale of course, divided into 12
62           * semitones per octave and 100 cents per semitone).           * semitones per octave and 100 cents per semitone).
63           *           *
64           * Note: MAX_PITCH (defined in global.h) has to be defined to an           * Note: CONFIG_MAX_PITCH (defined in config.h) has to be defined to an
65           * appropriate value, otherwise the behavior of this function is           * appropriate value, otherwise the behavior of this function is
66           * undefined, but most probably if MAX_PITCH is too small, the           * undefined, but most probably if CONFIG_MAX_PITCH is too small, the
67           * application will crash due to segmentation fault here.           * application will crash due to segmentation fault here.
68           *           *
69           * @param cents - pitch value in cents (+1200 cents means +1 octave)           * @param cents - pitch value in cents (+1200 cents means +1 octave)
70           * @returns  frequency ratio (e.g. +2.0 for +1 octave)           * @returns  frequency ratio (e.g. +2.0 for +1 octave)
71           */           */
72          inline static double CentsToFreqRatio(double Cents) {          inline static double CentsToFreqRatio(double Cents) {
73              int   index_int   = DoubleToInt(Cents); // integer index              int   index_int   = (int) (Cents);      // integer index
74              float index_fract = Cents - index_int;  // fractional part of index              float index_fract = Cents - index_int;  // fractional part of index
75              return pCentsToFreqTable[index_int] + index_fract * (pCentsToFreqTable[index_int+1] - pCentsToFreqTable[index_int]);              return pCentsToFreqTable[index_int] + index_fract * (pCentsToFreqTable[index_int+1] - pCentsToFreqTable[index_int]);
76          }          }
77    
78          template<class T_a, class T_b> inline static T_a Min(T_a a, T_b b) {      private:
79            static float  CentsToFreqTable[CONFIG_MAX_PITCH * 1200 * 2 + 1];
80            static float* pCentsToFreqTable;
81    
82            static float* InitCentsToFreqTable();
83    };
84    
85    /** @brief Real Time Math
86     *
87     * This is a template which provides customized methods for the desired low
88     * level implementation. The ASM_X86_MMX_SSE implementation of each method
89     * for example doesn't use 387 FPU instruction. This is needed for MMX
90     * algorithms which do not allow mixed MMX and 387 instructions.
91     */
92    template<implementation_t IMPL = CPP>
93    class __RTMath : public RTMathBase {
94        public:
95            // conversion using truncate
96            inline static int Int(const float a) {
97                switch (IMPL) {
98                    case CPP: {
99                        return (int) a;
100                    }
101                    #if CONFIG_ASM && ARCH_X86
102                    case ASM_X86_MMX_SSE: {
103                        int ret;
104                        asm (
105                            "cvttss2si %1, %0  # convert to int\n\t"
106                            : "=r" (ret)
107                            : "m" (a)
108                        );
109                        return ret;
110                    }
111                    #endif // CONFIG_ASM && ARCH_X86
112                }
113            }
114    
115            //for doubles and everything else except floats
116            template<class T_a> inline static int Int(const T_a a) {
117                return (int) a;
118            }
119    
120            inline static float Float(const int a) {
121                switch (IMPL) {
122                    case CPP: {
123                        return (float) a;
124                    }
125                    #if CONFIG_ASM && ARCH_X86
126                    case ASM_X86_MMX_SSE: {
127                        float ret;
128                        asm (
129                            "cvtsi2ss %1, %%xmm0  # convert to float\n\t"
130                            "movss    %%xmm0,%0   # output\n\t"
131                            : "=m" (ret)
132                            : "r" (a)
133                        );
134                        return ret;
135                    }
136                    #endif // CONFIG_ASM && ARCH_X86
137                }
138            }
139    
140    #if 0
141            //for everything except ints
142            template<class T_a> inline static float Float(T_a a) {
143                return (float) a;
144            }
145    #endif
146    
147            inline static float Sum(const float& a, const float& b) {
148                switch (IMPL) {
149                    case CPP: {
150                        return (a + b);
151                    }
152                    #if CONFIG_ASM && ARCH_X86
153                    case ASM_X86_MMX_SSE: {
154                        float ret;
155                        asm (
156                            "movss    %1, %%xmm0  # load a\n\t"
157                            "addss    %2, %%xmm0  # a + b\n\t"
158                            "movss    %%xmm0, %0  # output\n\t"
159                            : "=m" (ret)
160                            : "m" (a), "m" (b)
161                        );
162                        return ret;
163                    }
164                    #endif // CONFIG_ASM && ARCH_X86
165                }
166            }
167    
168            template<class T_a, class T_b> inline static T_a Sum(const T_a a, const T_b b) {
169                return (a + b);
170            }
171    
172            inline static float Sub(const float& a, const float& b) {
173                switch (IMPL) {
174                    case CPP: {
175                        return (a - b);
176                    }
177                    #if CONFIG_ASM && ARCH_X86
178                    case ASM_X86_MMX_SSE: {
179                        float ret;
180                        asm (
181                            "movss    %1, %%xmm0  # load a\n\t"
182                            "subss    %2, %%xmm0  # a - b\n\t"
183                            "movss    %%xmm0, %0  # output\n\t"
184                            : "=m" (ret)
185                            : "m" (a), "m" (b)
186                        );
187                        return ret;
188                    }
189                    #endif // CONFIG_ASM && ARCH_X86
190                }
191            }
192    
193            template<class T_a, class T_b> inline static T_a Sub(const T_a a, const T_b b) {
194                return (a - b);
195            }
196    
197            inline static float Mul(const float a, const float b) {
198                switch (IMPL) {
199                    case CPP: {
200                        return (a * b);
201                    }
202                    #if CONFIG_ASM && ARCH_X86
203                    case ASM_X86_MMX_SSE: {
204                        float ret;
205                        asm (
206                            "movss    %1, %%xmm0  # load a\n\t"
207                            "mulss    %2, %%xmm0  # a * b\n\t"
208                            "movss    %%xmm0, %0  # output\n\t"
209                            : "=m" (ret)
210                            : "m" (a), "m" (b)
211                        );
212                        return ret;
213                    }
214                    #endif // CONFIG_ASM && ARCH_X86
215                }
216            }
217    
218            template<class T_a, class T_b> inline static T_a Mul(const T_a a, const T_b b) {
219                return (a * b);
220            }
221    
222            inline static float Div(const float a, const float b) {
223                switch (IMPL) {
224                    case CPP: {
225                        return (a / b);
226                    }
227                    #if CONFIG_ASM && ARCH_X86
228                    case ASM_X86_MMX_SSE: {
229                        float ret;
230                        asm (
231                            "movss    %1, %%xmm0  # load a\n\t"
232                            "divss    %2, %%xmm0  # a / b\n\t"
233                            "movss    %%xmm0, %0  # output\n\t"
234                            : "=m" (ret)
235                            : "m" (a), "m" (b)
236                        );
237                        return ret;
238                    }
239                    #endif // CONFIG_ASM && ARCH_X86
240                }
241            }
242    
243            template<class T_a, class T_b> inline static T_a Div(const T_a a, const T_b b) {
244                return (a / b);
245            }
246    
247            inline static float Min(const float a, const float b) {
248                switch (IMPL) {
249                    case CPP: {
250                        return (b < a) ? b : a;
251                    }
252                    #if CONFIG_ASM && ARCH_X86
253                    case ASM_X86_MMX_SSE: {
254                        float ret;
255                        asm (
256                            "movss    %1, %%xmm0  # load a\n\t"
257                            "minss    %2, %%xmm0  # Minimum(a, b)\n\t"
258                            "movss    %%xmm0, %0  # output\n\t"
259                            : "=m" (ret)
260                            : "m" (a), "m" (b)
261                        );
262                        return ret;
263                    }
264                    #endif // CONFIG_ASM && ARCH_X86
265                }
266            }
267    
268            template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
269              return (b < a) ? b : a;              return (b < a) ? b : a;
270          }          }
271    
272          template<class T_a, class T_b> inline static T_a Max(T_a a, T_b b) {          inline static float Max(const float a, const float b) {
273                switch (IMPL) {
274                    case CPP: {
275                        return (b > a) ? b : a;
276                    }
277                    #if CONFIG_ASM && ARCH_X86
278                    case ASM_X86_MMX_SSE: {
279                        float ret;
280                        asm (
281                            "movss    %1, %%xmm0  # load a\n\t"
282                            "maxss    %2, %%xmm0  # Maximum(a, b)\n\t"
283                            "movss    %%xmm0, %0  # output\n\t"
284                            : "=m" (ret)
285                            : "m" (a), "m" (b)
286                        );
287                        return ret;
288                    }
289                    #endif // CONFIG_ASM && ARCH_X86
290                }
291            }
292    
293            template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
294              return (b > a) ? b : a;              return (b > a) ? b : a;
295          }          }
     private:  
         static float  CentsToFreqTable[MAX_PITCH * 1200 * 2 + 1];  
         static float* pCentsToFreqTable;  
296    
297          static float* InitCentsToFreqTable();          inline static float Fmodf(const float &a, const float &b) {
298                switch (IMPL) {
299                    case CPP: {
300                        return fmodf(a, b);
301                    }
302                    #if CONFIG_ASM && ARCH_X86
303                    case ASM_X86_MMX_SSE: {
304                        float ret;
305                        asm (
306                            "movss    %1, %%xmm0  # load a\n\t"
307                            "movss    %2, %%xmm1  # load b\n\t"
308                            "movss    %%xmm0,%%xmm2\n\t"
309                            "divss    %%xmm1, %%xmm2  # xmm2 = a / b\n\t"
310                            "cvttss2si %%xmm2, %%ecx  #convert to int\n\t"
311                            "cvtsi2ss %%ecx, %%xmm2  #convert back to float\n\t"
312                            "mulss    %%xmm1, %%xmm2  # xmm2 = b * int(a/b)\n\t"
313                            "subss    %%xmm2, %%xmm0  #sub a\n\t"
314                            "movss    %%xmm0, %0  # output\n\t"
315                            : "=m" (ret)
316                            : "m" (a), "m" (b)
317                            : "%ecx"
318                        );
319                        return ret;
320                    }
321                    #endif // CONFIG_ASM && ARCH_X86
322                }
323            }
324  };  };
325    
326    /// convenience typedef for using the default implementation (which is CPP)
327    typedef __RTMath<> RTMath;
328    
329  #endif // __RT_MATH_H__  #endif // __RT_MATH_H__

Legend:
Removed from v.53  
changed lines
  Added in v.617

  ViewVC Help
Powered by ViewVC