/[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 685 - (hide annotations) (download) (as text)
Tue Jul 5 19:30:37 2005 UTC (18 years, 8 months ago) by persson
File MIME type: text/x-c++hdr
File size: 12200 byte(s)
* gcc 4.0 compilation fixes

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 554 * Copyright (C) 2005 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 53 #include "global.h"
30    
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 319 private:
79 schoenebeck 554 static float CentsToFreqTable[CONFIG_MAX_PITCH * 1200 * 2 + 1];
80 schoenebeck 319 static float* pCentsToFreqTable;
81    
82     static float* InitCentsToFreqTable();
83     };
84    
85 schoenebeck 563 /** @brief Real Time Math
86 schoenebeck 319 *
87 schoenebeck 563 * 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 schoenebeck 319 */
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
99 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
109 persson 685 default: {
110     return (int) a;
111     }
112 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
123 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
134 persson 685 default: {
135     return (float) a;
136     }
137 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
150 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
162 persson 685 default: {
163     return (a + b);
164     }
165 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
175 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
187 persson 685 default: {
188     return (a - b);
189     }
190 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
200 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
212 persson 685 default: {
213     return (a * b);
214     }
215 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
225 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
237 persson 685 default: {
238     return (a / b);
239     }
240 schoenebeck 319 }
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 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
250 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
262 persson 685 default: {
263     return (b < a) ? b : a;
264     }
265 schoenebeck 319 }
266     }
267    
268     template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
269 schoenebeck 53 return (b < a) ? b : a;
270     }
271    
272 schoenebeck 319 inline static float Max(const float a, const float b) {
273     switch (IMPL) {
274 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
275 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
287 persson 685 default: {
288     return (b > a) ? b : a;
289     }
290 schoenebeck 319 }
291     }
292    
293     template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
294 schoenebeck 53 return (b > a) ? b : a;
295     }
296    
297 schoenebeck 319 inline static float Fmodf(const float &a, const float &b) {
298     switch (IMPL) {
299 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
300 schoenebeck 319 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 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
319 persson 685 default: {
320     return fmodf(a, b);
321     }
322 schoenebeck 319 }
323     }
324 schoenebeck 53 };
325    
326 schoenebeck 319 /// convenience typedef for using the default implementation (which is CPP)
327     typedef __RTMath<> RTMath;
328    
329 schoenebeck 53 #endif // __RT_MATH_H__

  ViewVC Help
Powered by ViewVC