/[svn]/linuxsampler/trunk/src/common/RTMath.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/RTMath.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 617 - (show annotations) (download) (as text)
Wed Jun 8 21:00:06 2005 UTC (18 years, 10 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 12209 byte(s)
* hand-crafted assembly optimization code can be disabled with
  './configure --disable-asm' (definitely not recommended)

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 Christian Schoenebeck *
7 * *
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 #include <stdint.h>
29 #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 enum implementation_t {
35 CPP,
36 ASM_X86_MMX_SSE
37 };
38
39 /** @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 class RTMathBase {
45 public:
46 /**
47 * 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 * 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 * Note: CONFIG_MAX_PITCH (defined in config.h) has to be defined to an
65 * appropriate value, otherwise the behavior of this function is
66 * undefined, but most probably if CONFIG_MAX_PITCH is too small, the
67 * 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 int index_int = (int) (Cents); // integer index
74 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 private:
79 static float CentsToFreqTable[CONFIG_MAX_PITCH * 1200 * 2 + 1];
80 static float* pCentsToFreqTable;
81
82 static float* InitCentsToFreqTable();
83 };
84
85 /** @brief Real Time Math
86 *
87 * 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 */
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 #if CONFIG_ASM && ARCH_X86
102 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 #endif // CONFIG_ASM && ARCH_X86
112 }
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 #if CONFIG_ASM && ARCH_X86
126 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 #endif // CONFIG_ASM && ARCH_X86
137 }
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 #if CONFIG_ASM && ARCH_X86
153 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 #endif // CONFIG_ASM && ARCH_X86
165 }
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 #if CONFIG_ASM && ARCH_X86
178 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 #endif // CONFIG_ASM && ARCH_X86
190 }
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 #if CONFIG_ASM && ARCH_X86
203 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 #endif // CONFIG_ASM && ARCH_X86
215 }
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 #if CONFIG_ASM && ARCH_X86
228 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 #endif // CONFIG_ASM && ARCH_X86
240 }
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 #if CONFIG_ASM && ARCH_X86
253 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 #endif // CONFIG_ASM && ARCH_X86
265 }
266 }
267
268 template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
269 return (b < a) ? b : a;
270 }
271
272 inline static float Max(const float a, const float b) {
273 switch (IMPL) {
274 case CPP: {
275 return (b > a) ? b : a;
276 }
277 #if CONFIG_ASM && ARCH_X86
278 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 #endif // CONFIG_ASM && ARCH_X86
290 }
291 }
292
293 template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
294 return (b > a) ? b : a;
295 }
296
297 inline static float Fmodf(const float &a, const float &b) {
298 switch (IMPL) {
299 case CPP: {
300 return fmodf(a, b);
301 }
302 #if CONFIG_ASM && ARCH_X86
303 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 #endif // CONFIG_ASM && ARCH_X86
322 }
323 }
324 };
325
326 /// convenience typedef for using the default implementation (which is CPP)
327 typedef __RTMath<> RTMath;
328
329 #endif // __RT_MATH_H__

  ViewVC Help
Powered by ViewVC