(file) Return to RTMath.h CVS log (file) (dir) Up to [ls] / linuxsampler / src / common

This file is part of LinuxSampler, which is licensed under the GNU GPL with the exception that USAGE of the source code, libraries and applications FOR COMMERCIAL HARDWARE OR SOFTWARE PRODUCTS IS NOT ALLOWED without prior written permission by the LinuxSampler authors. If you have questions on the subject, that are not yet covered by the FAQ, please contact us.


  1 schoenebeck 1.1 /***************************************************************************
  2                  *                                                                         *
  3                  *   LinuxSampler - modular, streaming capable sampler                     *
  4                  *                                                                         *
  5 schoenebeck 1.2  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
  6 schoenebeck 1.13  *   Copyright (C) 2005 - 2007 Christian Schoenebeck                       *
  7 schoenebeck 1.1   *                                                                         *
  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 1.4  #include <stdint.h>
 29 schoenebeck 1.14 #include "global_private.h"
 30 schoenebeck 1.1  
 31                  /// Needed for calculating frequency ratio used to pitch a sample
 32                  #define TWELVEHUNDREDTH_ROOT_OF_TWO	1.000577789506555
 33                  
 34 schoenebeck 1.3  enum implementation_t {
 35 schoenebeck 1.5      CPP,
 36                      ASM_X86_MMX_SSE
 37 schoenebeck 1.3  };
 38                  
 39 schoenebeck 1.7  /** @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 1.3  class RTMathBase {
 45 schoenebeck 1.1      public:
 46                          /**
 47 schoenebeck 1.4           * 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 1.1           * 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 1.6           * Note: CONFIG_MAX_PITCH (defined in config.h) has to be defined to an
 65 schoenebeck 1.1           * appropriate value, otherwise the behavior of this function is
 66 schoenebeck 1.6           * undefined, but most probably if CONFIG_MAX_PITCH is too small, the
 67 schoenebeck 1.1           * 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 1.3              int   index_int   = (int) (Cents);      // integer index
 74 schoenebeck 1.1              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 1.12         /**
 79                           * Inverse function to CentsToFreqRatio(). This function is a bit
 80                           * slow, so it should not be called too frequently.
 81                           */
 82                          static double FreqRatioToCents(double FreqRatio) {
 83                              return log(FreqRatio) / log(TWELVEHUNDREDTH_ROOT_OF_TWO);
 84                          }
 85                  
 86 schoenebeck 1.3      private:
 87                          static float* pCentsToFreqTable;
 88                  
 89                          static float* InitCentsToFreqTable();
 90                  };
 91                  
 92 schoenebeck 1.7  /** @brief Real Time Math
 93 schoenebeck 1.3   *
 94 schoenebeck 1.7   * This is a template which provides customized methods for the desired low
 95                   * level implementation. The ASM_X86_MMX_SSE implementation of each method
 96                   * for example doesn't use 387 FPU instruction. This is needed for MMX
 97                   * algorithms which do not allow mixed MMX and 387 instructions.
 98 schoenebeck 1.3   */
 99                  template<implementation_t IMPL = CPP>
100                  class __RTMath : public RTMathBase {
101                      public:
102                          // conversion using truncate
103                          inline static int Int(const float a) {
104                              switch (IMPL) {
105 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
106 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
107                                      int ret;
108                                      asm (
109                                          "cvttss2si %1, %0  # convert to int\n\t"
110                                          : "=r" (ret)
111                                          : "m" (a)
112                                      );
113                                      return ret;
114                                  }
115 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
116 persson     1.9                  default: {
117                                      return (int) a;
118                                  }
119 schoenebeck 1.3              }
120                          }
121                  
122                  	//for doubles and everything else except floats
123                          template<class T_a> inline static int Int(const T_a a) {
124                              return (int) a;
125                          }
126                  
127                          inline static float Float(const int a) {
128                              switch (IMPL) {
129 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
130 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
131                                      float ret;
132                                      asm (
133                                          "cvtsi2ss %1, %%xmm0  # convert to float\n\t"
134                                          "movss    %%xmm0,%0   # output\n\t"
135                                          : "=m" (ret)
136                                          : "r" (a)
137                                      );
138                                      return ret;
139                                  }
140 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
141 persson     1.9                  default: {
142                                      return (float) a;
143                                  }
144 schoenebeck 1.3              }
145                          }
146                  
147                  #if 0
148                          //for everything except ints
149                          template<class T_a> inline static float Float(T_a a) {
150                              return (float) a;
151                          }
152                  #endif
153                  
154                  	inline static float Sum(const float& a, const float& b) {
155                              switch (IMPL) {
156 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
157 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
158                                      float ret;
159                                      asm (
160                                          "movss    %1, %%xmm0  # load a\n\t"
161                                          "addss    %2, %%xmm0  # a + b\n\t"
162                                          "movss    %%xmm0, %0  # output\n\t"
163                                          : "=m" (ret)
164                                          : "m" (a), "m" (b)
165                                      );
166                                      return ret;
167                                  }
168 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
169 persson     1.9                  default: {
170                                      return (a + b);
171                                  }
172 schoenebeck 1.3              }
173                          }
174                  
175                          template<class T_a, class T_b> inline static T_a Sum(const T_a a, const T_b b) {
176                              return (a + b);
177                          }
178                  
179                          inline static float Sub(const float& a, const float& b) {
180                              switch (IMPL) {
181 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
182 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
183                                      float ret;
184                                      asm (
185                                          "movss    %1, %%xmm0  # load a\n\t"
186                                          "subss    %2, %%xmm0  # a - b\n\t"
187                                          "movss    %%xmm0, %0  # output\n\t"
188                                          : "=m" (ret)
189                                          : "m" (a), "m" (b)
190                                      );
191                                      return ret;
192                                  }
193 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
194 persson     1.9                  default: {
195                                      return (a - b);
196                                  }
197 schoenebeck 1.3              }
198                          }
199                  
200                          template<class T_a, class T_b> inline static T_a Sub(const T_a a, const T_b b) {
201                              return (a - b);
202                          }
203                  
204                          inline static float Mul(const float a, const float b) {
205                              switch (IMPL) {
206 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
207 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
208                                      float ret;
209                                      asm (
210                                          "movss    %1, %%xmm0  # load a\n\t"
211                                          "mulss    %2, %%xmm0  # a * b\n\t"
212                                          "movss    %%xmm0, %0  # output\n\t"
213                                          : "=m" (ret)
214                                          : "m" (a), "m" (b)
215                                      );
216                                      return ret;
217                                  }
218 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
219 persson     1.9                  default: {
220                                      return (a * b);
221                                  }
222 schoenebeck 1.3              }
223                          }
224                  
225                          template<class T_a, class T_b> inline static T_a Mul(const T_a a, const T_b b) {
226                              return (a * b);
227                          }
228                  
229                          inline static float Div(const float a, const float b) {
230                              switch (IMPL) {
231 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
232 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
233                                      float ret;
234                                      asm (
235                                          "movss    %1, %%xmm0  # load a\n\t"
236                                          "divss    %2, %%xmm0  # a / b\n\t"
237                                          "movss    %%xmm0, %0  # output\n\t"
238                                          : "=m" (ret)
239                                          : "m" (a), "m" (b)
240                                      );
241                                      return ret;
242                                  }
243 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
244 persson     1.9                  default: {
245                                      return (a / b);
246                                  }
247 schoenebeck 1.3              }
248                          }
249                  
250                          template<class T_a, class T_b> inline static T_a Div(const T_a a, const T_b b) {
251                              return (a / b);
252                          }
253                  
254                          inline static float Min(const float a, const float b) {
255                              switch (IMPL) {
256 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
257 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
258                                      float ret;
259                                      asm (
260                                          "movss    %1, %%xmm0  # load a\n\t"
261                                          "minss    %2, %%xmm0  # Minimum(a, b)\n\t"
262                                          "movss    %%xmm0, %0  # output\n\t"
263                                          : "=m" (ret)
264                                          : "m" (a), "m" (b)
265                                      );
266                                      return ret;
267                                  }
268 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
269 persson     1.9                  default: {
270 wylder      1.11                     return std::min(a, b);
271 persson     1.9                  }
272 schoenebeck 1.3              }
273                          }
274                  
275                          template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
276 schoenebeck 1.1              return (b < a) ? b : a;
277                          }
278                  
279 schoenebeck 1.3          inline static float Max(const float a, const float b) {
280                              switch (IMPL) {
281 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
282 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
283                                      float ret;
284                                      asm (
285                                          "movss    %1, %%xmm0  # load a\n\t"
286                                          "maxss    %2, %%xmm0  # Maximum(a, b)\n\t"
287                                          "movss    %%xmm0, %0  # output\n\t"
288                                          : "=m" (ret)
289                                          : "m" (a), "m" (b)
290                                      );
291                                      return ret;
292                                  }
293 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
294 persson     1.9                  default: {
295 wylder      1.11                     return std::max(a, b);
296 persson     1.9                  }
297 schoenebeck 1.3              }
298                          }
299                  
300                          template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
301 schoenebeck 1.1              return (b > a) ? b : a;
302                          }
303                  
304 schoenebeck 1.3          inline static float Fmodf(const float &a, const float &b) {
305                              switch (IMPL) {
306 schoenebeck 1.8                  #if CONFIG_ASM && ARCH_X86
307 schoenebeck 1.3                  case ASM_X86_MMX_SSE: {
308                                      float ret;
309                                      asm (
310                                          "movss    %1, %%xmm0  # load a\n\t"
311                                          "movss    %2, %%xmm1  # load b\n\t"
312                                          "movss    %%xmm0,%%xmm2\n\t"
313                                          "divss    %%xmm1, %%xmm2  # xmm2 = a / b\n\t"
314                                          "cvttss2si %%xmm2, %%ecx  #convert to int\n\t"
315                                          "cvtsi2ss %%ecx, %%xmm2  #convert back to float\n\t"
316                                          "mulss    %%xmm1, %%xmm2  # xmm2 = b * int(a/b)\n\t"
317                                          "subss    %%xmm2, %%xmm0  #sub a\n\t"
318                                          "movss    %%xmm0, %0  # output\n\t"
319                                          : "=m" (ret)
320                                          : "m" (a), "m" (b)
321                                          : "%ecx"
322                                      );
323                                      return ret;
324                                  }
325 schoenebeck 1.8                  #endif // CONFIG_ASM && ARCH_X86
326 persson     1.9                  default: {
327                                      return fmodf(a, b);
328                                  }
329 schoenebeck 1.3              }
330                          }
331 schoenebeck 1.1  };
332 schoenebeck 1.3  
333                  /// convenience typedef for using the default implementation (which is CPP)
334                  typedef __RTMath<> RTMath;
335 schoenebeck 1.1  
336                  #endif // __RT_MATH_H__

LinuxSampler Developers
Powered by
ViewCVS