/[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 1212 - (show annotations) (download) (as text)
Tue May 29 23:59:36 2007 UTC (16 years, 10 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 12423 byte(s)
* added highly experimental support for on-the-fly instrument editing
  within the sampler's process (by using instrument editor plugins),
  you'll notice the new "Registered instrument editors:" message on
  startup, the plugin path can be overridden at compile time with
  ./configure --enable-plugin-dir=/some/dir
* added a new LSCP command "EDIT INSTRUMENT <sampler-channel>" to spawn
  a matching instrument editor for the instrument on the given sampler
  channel (LSCP command syntax might be subject to change soon)
* config.h is not going to be installed along with liblinuxsampler's
  API header files anymore (not necessary anymore)
* take care of $(DESTDIR) when creating the instruments DB on 'make
  install' rule (needed for packaging and cross compilation)
* bumped version to 0.4.0.5cvs

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

  ViewVC Help
Powered by ViewVC