/[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 563 - (hide annotations) (download) (as text)
Sun May 22 20:43:32 2005 UTC (18 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 11957 byte(s)
* (re)implemented voice stealing algorithm "oldestvoiceonkey" and made it
  the default voice stealing algorithm
* added new LSCP command "GET SERVER INFO" which currently returns
  description and version about this sampler
* added some API documentation comments
* minor cleanup

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