/[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 829 - (hide annotations) (download) (as text)
Sat Jan 14 14:07:47 2006 UTC (18 years, 3 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 12496 byte(s)
* implemented portamento mode and solo mode (a.k.a 'mono mode'):
  all modes can be altered via standard GM messages, that is CC5 for
  altering portamento time, CC65 for enabling / disabling portamento
  mode, CC126 for enabling solo mode and CC127 for disabling solo mode
* fixed EG3 (pitch envelope) synthesis which was neutral all the time
* configure.in: do not automatically pick optimized gcc flags if the user
  already provided some on his own (as CXXFLAGS)

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 829 * Copyright (C) 2005, 2006 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 829 /**
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 319 private:
87 schoenebeck 554 static float CentsToFreqTable[CONFIG_MAX_PITCH * 1200 * 2 + 1];
88 schoenebeck 319 static float* pCentsToFreqTable;
89    
90     static float* InitCentsToFreqTable();
91     };
92    
93 schoenebeck 563 /** @brief Real Time Math
94 schoenebeck 319 *
95 schoenebeck 563 * This is a template which provides customized methods for the desired low
96     * level implementation. The ASM_X86_MMX_SSE implementation of each method
97     * for example doesn't use 387 FPU instruction. This is needed for MMX
98     * algorithms which do not allow mixed MMX and 387 instructions.
99 schoenebeck 319 */
100     template<implementation_t IMPL = CPP>
101     class __RTMath : public RTMathBase {
102     public:
103     // conversion using truncate
104     inline static int Int(const float a) {
105     switch (IMPL) {
106 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
107 schoenebeck 319 case ASM_X86_MMX_SSE: {
108     int ret;
109     asm (
110     "cvttss2si %1, %0 # convert to int\n\t"
111     : "=r" (ret)
112     : "m" (a)
113     );
114     return ret;
115     }
116 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
117 persson 685 default: {
118     return (int) a;
119     }
120 schoenebeck 319 }
121     }
122    
123     //for doubles and everything else except floats
124     template<class T_a> inline static int Int(const T_a a) {
125     return (int) a;
126     }
127    
128     inline static float Float(const int a) {
129     switch (IMPL) {
130 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
131 schoenebeck 319 case ASM_X86_MMX_SSE: {
132     float ret;
133     asm (
134     "cvtsi2ss %1, %%xmm0 # convert to float\n\t"
135     "movss %%xmm0,%0 # output\n\t"
136     : "=m" (ret)
137     : "r" (a)
138     );
139     return ret;
140     }
141 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
142 persson 685 default: {
143     return (float) a;
144     }
145 schoenebeck 319 }
146     }
147    
148     #if 0
149     //for everything except ints
150     template<class T_a> inline static float Float(T_a a) {
151     return (float) a;
152     }
153     #endif
154    
155     inline static float Sum(const float& a, const float& b) {
156     switch (IMPL) {
157 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
158 schoenebeck 319 case ASM_X86_MMX_SSE: {
159     float ret;
160     asm (
161     "movss %1, %%xmm0 # load a\n\t"
162     "addss %2, %%xmm0 # a + b\n\t"
163     "movss %%xmm0, %0 # output\n\t"
164     : "=m" (ret)
165     : "m" (a), "m" (b)
166     );
167     return ret;
168     }
169 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
170 persson 685 default: {
171     return (a + b);
172     }
173 schoenebeck 319 }
174     }
175    
176     template<class T_a, class T_b> inline static T_a Sum(const T_a a, const T_b b) {
177     return (a + b);
178     }
179    
180     inline static float Sub(const float& a, const float& b) {
181     switch (IMPL) {
182 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
183 schoenebeck 319 case ASM_X86_MMX_SSE: {
184     float ret;
185     asm (
186     "movss %1, %%xmm0 # load a\n\t"
187     "subss %2, %%xmm0 # a - b\n\t"
188     "movss %%xmm0, %0 # output\n\t"
189     : "=m" (ret)
190     : "m" (a), "m" (b)
191     );
192     return ret;
193     }
194 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
195 persson 685 default: {
196     return (a - b);
197     }
198 schoenebeck 319 }
199     }
200    
201     template<class T_a, class T_b> inline static T_a Sub(const T_a a, const T_b b) {
202     return (a - b);
203     }
204    
205     inline static float Mul(const float a, const float b) {
206     switch (IMPL) {
207 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
208 schoenebeck 319 case ASM_X86_MMX_SSE: {
209     float ret;
210     asm (
211     "movss %1, %%xmm0 # load a\n\t"
212     "mulss %2, %%xmm0 # a * b\n\t"
213     "movss %%xmm0, %0 # output\n\t"
214     : "=m" (ret)
215     : "m" (a), "m" (b)
216     );
217     return ret;
218     }
219 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
220 persson 685 default: {
221     return (a * b);
222     }
223 schoenebeck 319 }
224     }
225    
226     template<class T_a, class T_b> inline static T_a Mul(const T_a a, const T_b b) {
227     return (a * b);
228     }
229    
230     inline static float Div(const float a, const float b) {
231     switch (IMPL) {
232 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
233 schoenebeck 319 case ASM_X86_MMX_SSE: {
234     float ret;
235     asm (
236     "movss %1, %%xmm0 # load a\n\t"
237     "divss %2, %%xmm0 # a / b\n\t"
238     "movss %%xmm0, %0 # output\n\t"
239     : "=m" (ret)
240     : "m" (a), "m" (b)
241     );
242     return ret;
243     }
244 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
245 persson 685 default: {
246     return (a / b);
247     }
248 schoenebeck 319 }
249     }
250    
251     template<class T_a, class T_b> inline static T_a Div(const T_a a, const T_b b) {
252     return (a / b);
253     }
254    
255     inline static float Min(const float a, const float b) {
256     switch (IMPL) {
257 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
258 schoenebeck 319 case ASM_X86_MMX_SSE: {
259     float ret;
260     asm (
261     "movss %1, %%xmm0 # load a\n\t"
262     "minss %2, %%xmm0 # Minimum(a, b)\n\t"
263     "movss %%xmm0, %0 # output\n\t"
264     : "=m" (ret)
265     : "m" (a), "m" (b)
266     );
267     return ret;
268     }
269 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
270 persson 685 default: {
271 wylder 818 return std::min(a, b);
272 persson 685 }
273 schoenebeck 319 }
274     }
275    
276     template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
277 schoenebeck 53 return (b < a) ? b : a;
278     }
279    
280 schoenebeck 319 inline static float Max(const float a, const float b) {
281     switch (IMPL) {
282 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
283 schoenebeck 319 case ASM_X86_MMX_SSE: {
284     float ret;
285     asm (
286     "movss %1, %%xmm0 # load a\n\t"
287     "maxss %2, %%xmm0 # Maximum(a, b)\n\t"
288     "movss %%xmm0, %0 # output\n\t"
289     : "=m" (ret)
290     : "m" (a), "m" (b)
291     );
292     return ret;
293     }
294 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
295 persson 685 default: {
296 wylder 818 return std::max(a, b);
297 persson 685 }
298 schoenebeck 319 }
299     }
300    
301     template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
302 schoenebeck 53 return (b > a) ? b : a;
303     }
304    
305 schoenebeck 319 inline static float Fmodf(const float &a, const float &b) {
306     switch (IMPL) {
307 schoenebeck 617 #if CONFIG_ASM && ARCH_X86
308 schoenebeck 319 case ASM_X86_MMX_SSE: {
309     float ret;
310     asm (
311     "movss %1, %%xmm0 # load a\n\t"
312     "movss %2, %%xmm1 # load b\n\t"
313     "movss %%xmm0,%%xmm2\n\t"
314     "divss %%xmm1, %%xmm2 # xmm2 = a / b\n\t"
315     "cvttss2si %%xmm2, %%ecx #convert to int\n\t"
316     "cvtsi2ss %%ecx, %%xmm2 #convert back to float\n\t"
317     "mulss %%xmm1, %%xmm2 # xmm2 = b * int(a/b)\n\t"
318     "subss %%xmm2, %%xmm0 #sub a\n\t"
319     "movss %%xmm0, %0 # output\n\t"
320     : "=m" (ret)
321     : "m" (a), "m" (b)
322     : "%ecx"
323     );
324     return ret;
325     }
326 schoenebeck 617 #endif // CONFIG_ASM && ARCH_X86
327 persson 685 default: {
328     return fmodf(a, b);
329     }
330 schoenebeck 319 }
331     }
332 schoenebeck 53 };
333    
334 schoenebeck 319 /// convenience typedef for using the default implementation (which is CPP)
335     typedef __RTMath<> RTMath;
336    
337 schoenebeck 53 #endif // __RT_MATH_H__

  ViewVC Help
Powered by ViewVC