2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 These macros allow one to write code which can be compiled optimally depending on
24 what loop constructs the compiler can best generate code.
37 #define FOR_IS_FASTER 1
38 #define WHILE_IS_FASTER 0
40 #define PREINCREMENT_IS_FASTER 1
41 #define POSTINCREMENT_IS_FASTER 0
46 #define FOR_IS_FASTER 1
47 #define WHILE_IS_FASTER 0
49 #define PREINCREMENT_IS_FASTER 0
50 #define POSTINCREMENT_IS_FASTER 1
59 #define LOOP(length, stmt) for (int xxi=0; xxi<(length); ++xxi) { stmt; }
63 #define LOOP(length, stmt) \
64 { int xxn = (length); \
74 // above macros are not friendly to the debugger
77 #define LooP(length) for (int xxi=0; xxi<(length); ++xxi)
81 #define LooP(length) for (int xxi=(length); --xxi;)
85 /* faster loop macro, length is required to be larger than 0 */
86 #define LOOP1(length, stmt) \
87 { int xxn = (length); \
98 meanings of the indexing macros:
99 ZXP = dereference and pre or post increment
101 PZ = preincrement (if applicable)
102 ZP = postincrement (if applicable)
103 ZOFF = offset from the pointer of the first element of the array
104 (preincrement requires a ZOFF of 1 which is pre-subtracted from the
105 base pointer. For other indexing types ZOFF is zero)
108 #if PREINCREMENT_IS_FASTER
109 #define ZXP(z) (*++(z))
111 #define PZ(z) (++(z))
114 #elif POSTINCREMENT_IS_FASTER
115 #define ZXP(z) (*(z)++)
118 #define ZP(z) ((z)++)
122 // ACCESSING INLETS AND OUTLETS :
125 #define ZIN(i) (IN(i) - ZOFF) // get buffer pointer offset for iteration
126 #define ZIN0(i) (IN(i)[0]) // get first sample
129 #define ZOUT(i) (OUT(i) - ZOFF) // get buffer pointer offset for iteration
130 #define ZOUT0(i) (OUT(i)[0]) // get first sample
132 #include "SC_BoundsMacros.h"
136 // Efficiency notes: Clear and Copy was benchmarked in October 2008.
137 // See http://www.mcld.co.uk/blog/blog.php?217 and http://www.mcld.co.uk/blog/blog.php?218
139 // Set floating-point data to all zeros
140 inline void Clear(int numSamples
, float *out
)
142 // The memset approach is valid on any system using IEEE floating-point. On other systems, please check...
143 memset(out
, 0, numSamples
* sizeof(float));
146 inline void Copy(int numSamples
, float *out
, float *in
)
148 memcpy(out
, in
, numSamples
* sizeof(float));
151 inline void Fill(int numSamples
, float *out
, float level
)
154 LOOP(numSamples
, ZXP(out
) = level
; );
157 inline void Fill(int numSamples
, float *out
, float level
, float slope
)
160 LOOP(numSamples
, ZXP(out
) = level
; level
+= slope
; );
163 inline void Accum(int numSamples
, float *out
, float *in
)
167 LOOP(numSamples
, ZXP(out
) += ZXP(in
); );
170 inline void Scale(int numSamples
, float *out
, float level
)
173 LOOP(numSamples
, ZXP(out
) *= level
;);
176 inline float Scale(int numSamples
, float *out
, float level
, float slope
)
179 LOOP(numSamples
, ZXP(out
) *= level
; level
+= slope
;);
183 inline float Scale(int numSamples
, float *out
, float *in
, float level
, float slope
)
187 LOOP(numSamples
, ZXP(out
) = ZXP(in
) * level
; level
+= slope
;);
191 inline float ScaleMix(int numSamples
, float *out
, float *in
, float level
, float slope
)
195 LOOP(numSamples
, ZXP(out
) += ZXP(in
) * level
; level
+= slope
;);
199 inline void Scale(int numSamples
, float *out
, float *in
, float level
)
203 LOOP(numSamples
, ZXP(out
) = ZXP(in
) * level
; );
206 // in these the pointers are assumed to already have been pre-offset.
207 inline void ZCopy(int numSamples
, float *out
, const float *in
)
209 // pointers must be 8 byte aligned
210 //assert((((long)(out+ZOFF) & 7) == 0) && (((long)(in+ZOFF) & 7) == 0));
211 if (in
== out
) return;
212 if ((numSamples
& 1) == 0) {
213 // copying doubles is faster on powerpc.
214 double *outd
= (double*)(out
+ ZOFF
) - ZOFF
;
215 double *ind
= (double*)(in
+ ZOFF
) - ZOFF
;
216 LOOP(numSamples
>> 1, ZXP(outd
) = ZXP(ind
); );
218 LOOP(numSamples
, ZXP(out
) = ZXP(in
); );
222 inline void ZClear(int numSamples
, float *out
)
224 // pointers must be 8 byte aligned
225 //assert((((long)(out+ZOFF) & 7) == 0) && (((long)(in+ZOFF) & 7) == 0));
226 if ((numSamples
& 1) == 0) {
227 // copying doubles is faster on powerpc.
228 double *outd
= (double*)(out
+ ZOFF
) - ZOFF
;
229 LOOP(numSamples
>> 1, ZXP(outd
) = 0.; );
231 LOOP(numSamples
, ZXP(out
) = 0.f
; );
235 inline void ZAccum(int numSamples
, float *out
, float *in
)
237 LOOP(numSamples
, ZXP(out
) += ZXP(in
); );