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"
29 //////////////////////////////////////////////////////////////////////////////////////////////////
31 // FIXME: once we completely move to c++11, we should get rid of sc_fpclassify
33 // Visual C++ doesn't have fpclassify (C99), so define it here if needed
36 enum { FP_NORMAL
, FP_NAN
, FP_INFINITE
, FP_SUBNORMAL
};
38 static int sc_fpclassify(float x
)
41 int kind
= _fpclass((double)x
);
57 result
= FP_SUBNORMAL
;
60 result
= FP_SUBNORMAL
;
69 inline int sc_fpclassify(float x
)
71 return std::fpclassify(x
);
75 //////////////////////////////////////////////////////////////////////////////////////////////////
77 static InterfaceTable
*ft
;
79 struct CheckBadValues
: public Unit
85 // declare unit generator functions
88 void CheckBadValues_Ctor(CheckBadValues
* unit
);
89 void CheckBadValues_next(CheckBadValues
* unit
, int inNumSamples
);
92 static const char *CheckBadValues_fpclassString(int fpclass
);
93 inline int CheckBadValues_fold_fpclasses(int fpclass
);
95 //////////////////////////////////////////////////////////////////////////////////////////////////
97 void CheckBadValues_Ctor(CheckBadValues
* unit
)
99 unit
->prevclass
= FP_NORMAL
;
101 SETCALC(CheckBadValues_next
);
102 CheckBadValues_next(unit
, 1);
106 void CheckBadValues_next(CheckBadValues
* unit
, int inNumSamples
)
109 float *out
= ZOUT(0);
111 int post
= (int) ZIN0(2);
117 case 1: // post a line on every bad value
120 classification
= sc_fpclassify(samp
);
121 switch (classification
)
124 printf("Infinite number found in Synth %d, ID: %d\n", unit
->mParent
->mNode
.mID
, (int)id
);
128 printf("NaN found in Synth %d, ID: %d\n", unit
->mParent
->mNode
.mID
, (int)id
);
132 printf("Denormal found in Synth %d, ID: %d\n", unit
->mParent
->mNode
.mID
, (int)id
);
143 classification
= CheckBadValues_fold_fpclasses(sc_fpclassify(samp
));
144 if(classification
!= unit
->prevclass
) {
145 if(unit
->sameCount
== 0) {
146 printf("CheckBadValues: %s found in Synth %d, ID %d\n",
147 CheckBadValues_fpclassString(classification
), unit
->mParent
->mNode
.mID
, (int)id
);
149 printf("CheckBadValues: %s found in Synth %d, ID %d (previous %d values were %s)\n",
150 CheckBadValues_fpclassString(classification
), unit
->mParent
->mNode
.mID
, (int)id
,
151 (int)unit
->sameCount
, CheckBadValues_fpclassString(unit
->prevclass
)
156 switch (classification
)
171 unit
->prevclass
= classification
;
177 classification
= sc_fpclassify(samp
);
178 switch (classification
)
197 const char *CheckBadValues_fpclassString(int fpclass
)
200 case FP_NORMAL
: return "normal";
201 case FP_NAN
: return "NaN";
202 case FP_INFINITE
: return "infinity";
204 case FP_ZERO
: return "zero";
206 case FP_SUBNORMAL
: return "denormal";
207 default: return "unknown";
212 inline int CheckBadValues_fold_fpclasses(int fpclass
)
215 case FP_ZERO
: return FP_NORMAL
; // a bit hacky. we mean "zero is fine too".
216 default: return fpclass
;
220 inline int CheckBadValues_fold_fpclasses(int fpclass
)
226 ////////////////////////////////////////////////////////////////////
228 // the load function is called by the host when the plug-in is loaded
233 DefineSimpleUnit(CheckBadValues
);