/[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 554 - (hide annotations) (download) (as text)
Thu May 19 19:25:14 2005 UTC (18 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 11565 byte(s)
* All compile time options are now centrally alterable as arguments to the
  ./configure script. All options are C Macros beginning with CONFIG_
  prefix and will be placed into auto generated config.h file.

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

  ViewVC Help
Powered by ViewVC