/[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 554 - (show 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 /***************************************************************************
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 class RTMathBase {
40 public:
41 /**
42 * 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 * 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 * Note: CONFIG_MAX_PITCH (defined in config.h) has to be defined to an
60 * appropriate value, otherwise the behavior of this function is
61 * undefined, but most probably if CONFIG_MAX_PITCH is too small, the
62 * 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 int index_int = (int) (Cents); // integer index
69 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 private:
74 static float CentsToFreqTable[CONFIG_MAX_PITCH * 1200 * 2 + 1];
75 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 #if ARCH_X86
94 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 #endif // ARCH_X86
104 }
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 #if ARCH_X86
118 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 #endif // ARCH_X86
129 }
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 #if ARCH_X86
145 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 #endif // ARCH_X86
157 }
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 #if ARCH_X86
170 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 #endif // ARCH_X86
182 }
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 #if ARCH_X86
195 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 #endif // ARCH_X86
207 }
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 #if ARCH_X86
220 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 #endif // ARCH_X86
232 }
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 #if ARCH_X86
245 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 #endif // ARCH_X86
257 }
258 }
259
260 template<class T_a, class T_b> inline static T_a Min(const T_a a, const T_b b) {
261 return (b < a) ? b : a;
262 }
263
264 inline static float Max(const float a, const float b) {
265 switch (IMPL) {
266 case CPP: {
267 return (b > a) ? b : a;
268 }
269 #if ARCH_X86
270 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 #endif // ARCH_X86
282 }
283 }
284
285 template<class T_a, class T_b> inline static T_a Max(const T_a a, const T_b b) {
286 return (b > a) ? b : a;
287 }
288
289 inline static float Fmodf(const float &a, const float &b) {
290 switch (IMPL) {
291 case CPP: {
292 return fmodf(a, b);
293 }
294 #if ARCH_X86
295 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 #endif // ARCH_X86
314 }
315 }
316 };
317
318 /// convenience typedef for using the default implementation (which is CPP)
319 typedef __RTMath<> RTMath;
320
321 #endif // __RT_MATH_H__

  ViewVC Help
Powered by ViewVC