FFT: Prevent user from attempting hops smaller than SC's block size
[supercollider.git] / server / plugins / TestUGens.cpp
blob636d458e8e28e5e230ec7a073869928948760f48
1 /*
2 * TestUGens.cpp
3 * Plugins
4 * Copyright (c) 2007 Scott Wilson <i@scottwilson.ca>. All rights reserved.
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
20 * Created by Scott Wilson on 22/06/2007.
21 * Modified by James Harkins on 28/07/2007.
26 #include "SC_PlugIn.h"
27 #include <cstdio>
29 //////////////////////////////////////////////////////////////////////////////////////////////////
31 // Visual C++ doesn't have fpclassify (C99), so define it here if needed
32 #ifdef _MSC_VER
33 #include <float.h>
34 enum { FP_NORMAL, FP_NAN, FP_INFINITE, FP_SUBNORMAL };
36 static int sc_fpclassify(float x)
38 int result;
39 int kind = _fpclass((double)x);
40 switch (kind)
42 case _FPCLASS_NINF:
43 result = FP_INFINITE;
44 break;
45 case _FPCLASS_PINF:
46 result = FP_INFINITE;
47 break;
48 case _FPCLASS_SNAN:
49 result = FP_NAN;
50 break;
51 case _FPCLASS_QNAN:
52 result = FP_NAN;
53 break;
54 case _FPCLASS_ND:
55 result = FP_SUBNORMAL;
56 break;
57 case _FPCLASS_PD:
58 result = FP_SUBNORMAL;
59 break;
60 default:
61 result = FP_NORMAL;
63 return result;
66 #else
67 inline int sc_fpclassify(float x)
69 return std::fpclassify(x);
71 #endif // _WIN32
73 //////////////////////////////////////////////////////////////////////////////////////////////////
75 static InterfaceTable *ft;
77 struct CheckBadValues : public Unit
79 long sameCount;
80 int prevclass;
83 // declare unit generator functions
84 extern "C"
86 void CheckBadValues_Ctor(CheckBadValues* unit);
87 void CheckBadValues_next(CheckBadValues* unit, int inNumSamples);
90 static const char *CheckBadValues_fpclassString(int fpclass);
91 inline int CheckBadValues_fold_fpclasses(int fpclass);
93 //////////////////////////////////////////////////////////////////////////////////////////////////
95 void CheckBadValues_Ctor(CheckBadValues* unit)
97 unit->prevclass = FP_NORMAL;
98 unit->sameCount = 0;
99 SETCALC(CheckBadValues_next);
100 CheckBadValues_next(unit, 1);
104 void CheckBadValues_next(CheckBadValues* unit, int inNumSamples)
106 float *in = ZIN(0);
107 float *out = ZOUT(0);
108 float id = ZIN0(1);
109 int post = (int) ZIN0(2);
111 float samp;
112 int classification;
114 switch(post) {
115 case 1: // post a line on every bad value
116 LOOP1(inNumSamples,
117 samp = ZXP(in);
118 classification = sc_fpclassify(samp);
119 switch (classification)
121 case FP_INFINITE:
122 printf("Infinite number found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id);
123 ZXP(out) = 2;
124 break;
125 case FP_NAN:
126 printf("NaN found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id);
127 ZXP(out) = 1;
128 break;
129 case FP_SUBNORMAL:
130 printf("Denormal found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id);
131 ZXP(out) = 3;
132 break;
133 default:
134 ZXP(out) = 0;
137 break;
138 case 2:
139 LOOP1(inNumSamples,
140 samp = ZXP(in);
141 classification = CheckBadValues_fold_fpclasses(sc_fpclassify(samp));
142 if(classification != unit->prevclass) {
143 if(unit->sameCount == 0) {
144 printf("CheckBadValues: %s found in Synth %d, ID %d\n",
145 CheckBadValues_fpclassString(classification), unit->mParent->mNode.mID, (int)id);
146 } else {
147 printf("CheckBadValues: %s found in Synth %d, ID %d (previous %d values were %s)\n",
148 CheckBadValues_fpclassString(classification), unit->mParent->mNode.mID, (int)id,
149 (int)unit->sameCount, CheckBadValues_fpclassString(unit->prevclass)
152 unit->sameCount = 0;
154 switch (classification)
156 case FP_INFINITE:
157 ZXP(out) = 2;
158 break;
159 case FP_NAN:
160 ZXP(out) = 1;
161 break;
162 case FP_SUBNORMAL:
163 ZXP(out) = 3;
164 break;
165 default:
166 ZXP(out) = 0;
168 unit->sameCount++;
169 unit->prevclass = classification;
171 break;
172 default: // no post
173 LOOP1(inNumSamples,
174 samp = ZXP(in);
175 classification = sc_fpclassify(samp);
176 switch (classification)
178 case FP_INFINITE:
179 ZXP(out) = 2;
180 break;
181 case FP_NAN:
182 ZXP(out) = 1;
183 break;
184 case FP_SUBNORMAL:
185 ZXP(out) = 3;
186 break;
187 default:
188 ZXP(out) = 0;
191 break;
195 const char *CheckBadValues_fpclassString(int fpclass)
197 switch(fpclass) {
198 case FP_NORMAL: return "normal";
199 case FP_NAN: return "NaN";
200 case FP_INFINITE: return "infinity";
201 #ifndef _WIN32
202 case FP_ZERO: return "zero";
203 #endif
204 case FP_SUBNORMAL: return "denormal";
205 default: return "unknown";
209 #ifndef _WIN32
210 inline int CheckBadValues_fold_fpclasses(int fpclass)
212 switch(fpclass) {
213 case FP_ZERO: return FP_NORMAL; // a bit hacky. we mean "zero is fine too".
214 default: return fpclass;
217 #else
218 inline int CheckBadValues_fold_fpclasses(int fpclass)
220 return fpclass;
222 #endif
224 ////////////////////////////////////////////////////////////////////
226 // the load function is called by the host when the plug-in is loaded
227 PluginLoad(Test)
229 ft = inTable;
231 DefineSimpleUnit(CheckBadValues);