/[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 818 by wylder, Thu Dec 22 19:35:42 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                    #if CONFIG_ASM && ARCH_X86
99                    case ASM_X86_MMX_SSE: {
100                        int ret;
101                        asm (
102                            "cvttss2si %1, %0  # convert to int\n\t"
103                            : "=r" (ret)
104                            : "m" (a)
105                        );
106                        return ret;
107                    }
108                    #endif // CONFIG_ASM && ARCH_X86
109                    default: {
110                        return (int) a;
111                    }
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                    #if CONFIG_ASM && ARCH_X86
123                    case ASM_X86_MMX_SSE: {
124                        float ret;
125                        asm (
126                            "cvtsi2ss %1, %%xmm0  # convert to float\n\t"
127                            "movss    %%xmm0,%0   # output\n\t"
128                            : "=m" (ret)
129                            : "r" (a)
130                        );
131                        return ret;
132                    }
133                    #endif // CONFIG_ASM && ARCH_X86
134                    default: {
135                        return (float) a;
136                    }
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                    #if CONFIG_ASM && ARCH_X86
150                    case ASM_X86_MMX_SSE: {
151                        float ret;
152                        asm (
153                            "movss    %1, %%xmm0  # load a\n\t"
154                            "addss    %2, %%xmm0  # a + b\n\t"
155                            "movss    %%xmm0, %0  # output\n\t"
156                            : "=m" (ret)
157                            : "m" (a), "m" (b)
158                        );
159                        return ret;
160                    }
161                    #endif // CONFIG_ASM && ARCH_X86
162                    default: {
163                        return (a + b);
164                    }
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                    #if CONFIG_ASM && ARCH_X86
175                    case ASM_X86_MMX_SSE: {
176                        float ret;
177                        asm (
178                            "movss    %1, %%xmm0  # load a\n\t"
179                            "subss    %2, %%xmm0  # a - b\n\t"
180                            "movss    %%xmm0, %0  # output\n\t"
181                            : "=m" (ret)
182                            : "m" (a), "m" (b)
183                        );
184                        return ret;
185                    }
186                    #endif // CONFIG_ASM && ARCH_X86
187                    default: {
188                        return (a - b);
189                    }
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                    #if CONFIG_ASM && ARCH_X86
200                    case ASM_X86_MMX_SSE: {
201                        float ret;
202                        asm (
203                            "movss    %1, %%xmm0  # load a\n\t"
204                            "mulss    %2, %%xmm0  # a * b\n\t"
205                            "movss    %%xmm0, %0  # output\n\t"
206                            : "=m" (ret)
207                            : "m" (a), "m" (b)
208                        );
209                        return ret;
210                    }
211                    #endif // CONFIG_ASM && ARCH_X86
212                    default: {
213                        return (a * b);
214                    }
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                    #if CONFIG_ASM && ARCH_X86
225                    case ASM_X86_MMX_SSE: {
226                        float ret;
227                        asm (
228                            "movss    %1, %%xmm0  # load a\n\t"
229                            "divss    %2, %%xmm0  # a / b\n\t"
230                            "movss    %%xmm0, %0  # output\n\t"
231                            : "=m" (ret)
232                            : "m" (a), "m" (b)
233                        );
234                        return ret;
235                    }
236                    #endif // CONFIG_ASM && ARCH_X86
237                    default: {
238                        return (a / b);
239                    }
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                    #if CONFIG_ASM && ARCH_X86
250                    case ASM_X86_MMX_SSE: {
251                        float ret;
252                        asm (
253                            "movss    %1, %%xmm0  # load a\n\t"
254                            "minss    %2, %%xmm0  # Minimum(a, b)\n\t"
255                            "movss    %%xmm0, %0  # output\n\t"
256                            : "=m" (ret)
257                            : "m" (a), "m" (b)
258                        );
259                        return ret;
260                    }
261                    #endif // CONFIG_ASM && ARCH_X86
262                    default: {
263                        return std::min(a, b);
264                    }
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                    #if CONFIG_ASM && ARCH_X86
275                    case ASM_X86_MMX_SSE: {
276                        float ret;
277                        asm (
278                            "movss    %1, %%xmm0  # load a\n\t"
279                            "maxss    %2, %%xmm0  # Maximum(a, b)\n\t"
280                            "movss    %%xmm0, %0  # output\n\t"
281                            : "=m" (ret)
282                            : "m" (a), "m" (b)
283                        );
284                        return ret;
285                    }
286                    #endif // CONFIG_ASM && ARCH_X86
287                    default: {
288                        return std::max(a, b);
289                    }
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                    #if CONFIG_ASM && ARCH_X86
300                    case ASM_X86_MMX_SSE: {
301                        float ret;
302                        asm (
303                            "movss    %1, %%xmm0  # load a\n\t"
304                            "movss    %2, %%xmm1  # load b\n\t"
305                            "movss    %%xmm0,%%xmm2\n\t"
306                            "divss    %%xmm1, %%xmm2  # xmm2 = a / b\n\t"
307                            "cvttss2si %%xmm2, %%ecx  #convert to int\n\t"
308                            "cvtsi2ss %%ecx, %%xmm2  #convert back to float\n\t"
309                            "mulss    %%xmm1, %%xmm2  # xmm2 = b * int(a/b)\n\t"
310                            "subss    %%xmm2, %%xmm0  #sub a\n\t"
311                            "movss    %%xmm0, %0  # output\n\t"
312                            : "=m" (ret)
313                            : "m" (a), "m" (b)
314                            : "%ecx"
315                        );
316                        return ret;
317                    }
318                    #endif // CONFIG_ASM && ARCH_X86
319                    default: {
320                        return fmodf(a, b);
321                    }
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.818

  ViewVC Help
Powered by ViewVC