summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/d_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/d_ctl.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/d_ctl.c783
1 files changed, 0 insertions, 783 deletions
diff --git a/apps/plugins/pdbox/PDa/src/d_ctl.c b/apps/plugins/pdbox/PDa/src/d_ctl.c
index d3262af800..809899addf 100644
--- a/apps/plugins/pdbox/PDa/src/d_ctl.c
+++ b/apps/plugins/pdbox/PDa/src/d_ctl.c
@@ -782,787 +782,4 @@ void d_ctl_setup(void)
782} 782}
783 783
784#endif 784#endif
785/* Copyright (c) 1997-1999 Miller Puckette.
786* For information on usage and redistribution, and for a DISCLAIMER OF ALL
787* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
788
789/* sig~ and line~ control-to-signal converters;
790 snapshot~ signal-to-control converter.
791*/
792
793#include "m_pd.h"
794#include "math.h"
795
796/* -------------------------- sig~ ------------------------------ */
797static t_class *sig_tilde_class;
798
799typedef struct _sig
800{
801 t_object x_obj;
802 float x_f;
803} t_sig;
804
805static t_int *sig_tilde_perform(t_int *w)
806{
807 t_float f = *(t_float *)(w[1]);
808 t_float *out = (t_float *)(w[2]);
809 int n = (int)(w[3]);
810 while (n--)
811 *out++ = f;
812 return (w+4);
813}
814
815static t_int *sig_tilde_perf8(t_int *w)
816{
817 t_float f = *(t_float *)(w[1]);
818 t_float *out = (t_float *)(w[2]);
819 int n = (int)(w[3]);
820
821 for (; n; n -= 8, out += 8)
822 {
823 out[0] = f;
824 out[1] = f;
825 out[2] = f;
826 out[3] = f;
827 out[4] = f;
828 out[5] = f;
829 out[6] = f;
830 out[7] = f;
831 }
832 return (w+4);
833}
834
835void dsp_add_scalarcopy(t_sample *in, t_sample *out, int n)
836{
837 if (n&7)
838 dsp_add(sig_tilde_perform, 3, in, out, n);
839 else
840 dsp_add(sig_tilde_perf8, 3, in, out, n);
841}
842
843static void sig_tilde_float(t_sig *x, t_float f)
844{
845 x->x_f = f;
846}
847
848static void sig_tilde_dsp(t_sig *x, t_signal **sp)
849{
850 dsp_add(sig_tilde_perform, 3, &x->x_f, sp[0]->s_vec, sp[0]->s_n);
851}
852
853static void *sig_tilde_new(t_floatarg f)
854{
855 t_sig *x = (t_sig *)pd_new(sig_tilde_class);
856 x->x_f = f;
857 outlet_new(&x->x_obj, gensym("signal"));
858 return (x);
859}
860
861static void sig_tilde_setup(void)
862{
863 sig_tilde_class = class_new(gensym("sig~"), (t_newmethod)sig_tilde_new, 0,
864 sizeof(t_sig), 0, A_DEFFLOAT, 0);
865 class_addfloat(sig_tilde_class, (t_method)sig_tilde_float);
866 class_addmethod(sig_tilde_class, (t_method)sig_tilde_dsp, gensym("dsp"), 0);
867}
868
869
870#ifndef FIXEDPOINT
871
872/* -------------------------- line~ ------------------------------ */
873static t_class *line_tilde_class;
874
875typedef struct _line
876{
877 t_object x_obj;
878 float x_target;
879 float x_value;
880 float x_biginc;
881 float x_inc;
882 float x_1overn;
883 float x_dspticktomsec;
884 float x_inletvalue;
885 float x_inletwas;
886 int x_ticksleft;
887 int x_retarget;
888} t_line;
889
890static t_int *line_tilde_perform(t_int *w)
891{
892 t_line *x = (t_line *)(w[1]);
893 t_float *out = (t_float *)(w[2]);
894 int n = (int)(w[3]);
895 float f = x->x_value;
896
897 if (PD_BIGORSMALL(f))
898 x->x_value = f = 0;
899 if (x->x_retarget)
900 {
901 int nticks = x->x_inletwas * x->x_dspticktomsec;
902 if (!nticks) nticks = 1;
903 x->x_ticksleft = nticks;
904 x->x_biginc = (x->x_target - x->x_value)/(float)nticks;
905 x->x_inc = x->x_1overn * x->x_biginc;
906 x->x_retarget = 0;
907 }
908 if (x->x_ticksleft)
909 {
910 float f = x->x_value;
911 while (n--) *out++ = f, f += x->x_inc;
912 x->x_value += x->x_biginc;
913 x->x_ticksleft--;
914 }
915 else
916 {
917 x->x_value = x->x_target;
918 while (n--) *out++ = x->x_value;
919 }
920 return (w+4);
921}
922
923static void line_tilde_float(t_line *x, t_float f)
924{
925 if (x->x_inletvalue <= 0)
926 {
927 x->x_target = x->x_value = f;
928 x->x_ticksleft = x->x_retarget = 0;
929 }
930 else
931 {
932 x->x_target = f;
933 x->x_retarget = 1;
934 x->x_inletwas = x->x_inletvalue;
935 x->x_inletvalue = 0;
936 }
937}
938
939static void line_tilde_stop(t_line *x)
940{
941 x->x_target = x->x_value;
942 x->x_ticksleft = x->x_retarget = 0;
943}
944
945static void line_tilde_dsp(t_line *x, t_signal **sp)
946{
947 dsp_add(line_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
948 x->x_1overn = 1./sp[0]->s_n;
949 x->x_dspticktomsec = sp[0]->s_sr / (1000 * sp[0]->s_n);
950}
951
952static void *line_tilde_new(void)
953{
954 t_line *x = (t_line *)pd_new(line_tilde_class);
955 outlet_new(&x->x_obj, gensym("signal"));
956 floatinlet_new(&x->x_obj, &x->x_inletvalue);
957 x->x_ticksleft = x->x_retarget = 0;
958 x->x_value = x->x_target = x->x_inletvalue = x->x_inletwas = 0;
959 return (x);
960}
961
962static void line_tilde_setup(void)
963{
964 line_tilde_class = class_new(gensym("line~"), line_tilde_new, 0,
965 sizeof(t_line), 0, 0);
966 class_addfloat(line_tilde_class, (t_method)line_tilde_float);
967 class_addmethod(line_tilde_class, (t_method)line_tilde_dsp,
968 gensym("dsp"), 0);
969 class_addmethod(line_tilde_class, (t_method)line_tilde_stop,
970 gensym("stop"), 0);
971}
972
973/* -------------------------- vline~ ------------------------------ */
974static t_class *vline_tilde_class;
975
976typedef struct _vseg
977{
978 double s_targettime;
979 double s_starttime;
980 float s_target;
981 struct _vseg *s_next;
982} t_vseg;
983
984typedef struct _vline
985{
986 t_object x_obj;
987 double x_value;
988 double x_inc;
989 double x_referencetime;
990 double x_samppermsec;
991 double x_msecpersamp;
992 double x_targettime;
993 float x_target;
994 float x_inlet1;
995 float x_inlet2;
996 t_vseg *x_list;
997} t_vline;
998
999static t_int *vline_tilde_perform(t_int *w)
1000{
1001 t_vline *x = (t_vline *)(w[1]);
1002 t_float *out = (t_float *)(w[2]);
1003 int n = (int)(w[3]), i;
1004 double f = x->x_value;
1005 double inc = x->x_inc;
1006 double msecpersamp = x->x_msecpersamp;
1007 double samppermsec = x->x_samppermsec;
1008 double timenow = clock_gettimesince(x->x_referencetime) - n * msecpersamp;
1009 t_vseg *s = x->x_list;
1010 for (i = 0; i < n; i++)
1011 {
1012 double timenext = timenow + msecpersamp;
1013 checknext:
1014 if (s)
1015 {
1016 /* has starttime elapsed? If so update value and increment */
1017 if (s->s_starttime < timenext)
1018 {
1019 if (x->x_targettime <= timenext)
1020 f = x->x_target, inc = 0;
1021 /* if zero-length segment bash output value */
1022 if (s->s_targettime <= s->s_starttime)
1023 {
1024 f = s->s_target;
1025 inc = 0;
1026 }
1027 else
1028 {
1029 double incpermsec = (s->s_target - f)/
1030 (s->s_targettime - s->s_starttime);
1031 f = f + incpermsec * (timenext - s->s_starttime);
1032 inc = incpermsec * msecpersamp;
1033 }
1034 x->x_inc = inc;
1035 x->x_target = s->s_target;
1036 x->x_targettime = s->s_targettime;
1037 x->x_list = s->s_next;
1038 t_freebytes(s, sizeof(*s));
1039 s = x->x_list;
1040 goto checknext;
1041 }
1042 }
1043 if (x->x_targettime <= timenext)
1044 f = x->x_target, inc = x->x_inc = 0, x->x_targettime = 1e20;
1045 *out++ = f;
1046 f = f + inc;
1047 timenow = timenext;
1048 }
1049 x->x_value = f;
1050 return (w+4);
1051}
1052
1053static void vline_tilde_stop(t_vline *x)
1054{
1055 t_vseg *s1, *s2;
1056 for (s1 = x->x_list; s1; s1 = s2)
1057 s2 = s1->s_next, t_freebytes(s1, sizeof(*s1));
1058 x->x_list = 0;
1059 x->x_inc = 0;
1060 x->x_inlet1 = x->x_inlet2 = 0;
1061 x->x_target = x->x_value;
1062 x->x_targettime = 1e20;
1063}
1064
1065static void vline_tilde_float(t_vline *x, t_float f)
1066{
1067 double timenow = clock_gettimesince(x->x_referencetime);
1068 float inlet1 = (x->x_inlet1 < 0 ? 0 : x->x_inlet1);
1069 float inlet2 = x->x_inlet2;
1070 double starttime = timenow + inlet2;
1071 t_vseg *s1, *s2, *deletefrom = 0, *snew;
1072 if (PD_BIGORSMALL(f))
1073 f = 0;
1074
1075 /* negative delay input means stop and jump immediately to new value */
1076 if (inlet2 < 0)
1077 {
1078 x->x_value = f;
1079 vline_tilde_stop(x);
1080 return;
1081 }
1082 snew = (t_vseg *)t_getbytes(sizeof(*snew));
1083 /* check if we supplant the first item in the list. We supplant
1084 an item by having an earlier starttime, or an equal starttime unless
1085 the equal one was instantaneous and the new one isn't (in which case
1086 we'll do a jump-and-slide starting at that time.) */
1087 if (!x->x_list || x->x_list->s_starttime > starttime ||
1088 (x->x_list->s_starttime == starttime &&
1089 (x->x_list->s_targettime > x->x_list->s_starttime || inlet1 <= 0)))
1090 {
1091 deletefrom = x->x_list;
1092 x->x_list = snew;
1093 }
1094 else
1095 {
1096 for (s1 = x->x_list; s2 = s1->s_next; s1 = s2)
1097 {
1098 if (s2->s_starttime > starttime ||
1099 (s2->s_starttime == starttime &&
1100 (s2->s_targettime > s2->s_starttime || inlet1 <= 0)))
1101 {
1102 deletefrom = s2;
1103 s1->s_next = snew;
1104 goto didit;
1105 }
1106 }
1107 s1->s_next = snew;
1108 deletefrom = 0;
1109 didit: ;
1110 }
1111 while (deletefrom)
1112 {
1113 s1 = deletefrom->s_next;
1114 t_freebytes(deletefrom, sizeof(*deletefrom));
1115 deletefrom = s1;
1116 }
1117 snew->s_next = 0;
1118 snew->s_target = f;
1119 snew->s_starttime = starttime;
1120 snew->s_targettime = starttime + inlet1;
1121 x->x_inlet1 = x->x_inlet2 = 0;
1122}
1123
1124static void vline_tilde_dsp(t_vline *x, t_signal **sp)
1125{
1126 dsp_add(vline_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
1127 x->x_samppermsec = ((double)(sp[0]->s_sr)) / 1000;
1128 x->x_msecpersamp = ((double)1000) / sp[0]->s_sr;
1129}
1130 785
1131static void *vline_tilde_new(void)
1132{
1133 t_vline *x = (t_vline *)pd_new(vline_tilde_class);
1134 outlet_new(&x->x_obj, gensym("signal"));
1135 floatinlet_new(&x->x_obj, &x->x_inlet1);
1136 floatinlet_new(&x->x_obj, &x->x_inlet2);
1137 x->x_inlet1 = x->x_inlet2 = 0;
1138 x->x_value = x->x_inc = 0;
1139 x->x_referencetime = clock_getlogicaltime();
1140 x->x_list = 0;
1141 x->x_samppermsec = 0;
1142 x->x_targettime = 1e20;
1143 return (x);
1144}
1145
1146static void vline_tilde_setup(void)
1147{
1148 vline_tilde_class = class_new(gensym("vline~"), vline_tilde_new,
1149 (t_method)vline_tilde_stop, sizeof(t_vline), 0, 0);
1150 class_addfloat(vline_tilde_class, (t_method)vline_tilde_float);
1151 class_addmethod(vline_tilde_class, (t_method)vline_tilde_dsp,
1152 gensym("dsp"), 0);
1153 class_addmethod(vline_tilde_class, (t_method)vline_tilde_stop,
1154 gensym("stop"), 0);
1155}
1156
1157/* -------------------------- snapshot~ ------------------------------ */
1158static t_class *snapshot_tilde_class;
1159
1160typedef struct _snapshot
1161{
1162 t_object x_obj;
1163 t_sample x_value;
1164 float x_f;
1165} t_snapshot;
1166
1167static void *snapshot_tilde_new(void)
1168{
1169 t_snapshot *x = (t_snapshot *)pd_new(snapshot_tilde_class);
1170 x->x_value = 0;
1171 outlet_new(&x->x_obj, &s_float);
1172 x->x_f = 0;
1173 return (x);
1174}
1175
1176static t_int *snapshot_tilde_perform(t_int *w)
1177{
1178 t_float *in = (t_float *)(w[1]);
1179 t_float *out = (t_float *)(w[2]);
1180 *out = *in;
1181 return (w+3);
1182}
1183
1184static void snapshot_tilde_dsp(t_snapshot *x, t_signal **sp)
1185{
1186 dsp_add(snapshot_tilde_perform, 2, sp[0]->s_vec + (sp[0]->s_n-1),
1187 &x->x_value);
1188}
1189
1190static void snapshot_tilde_bang(t_snapshot *x)
1191{
1192 outlet_float(x->x_obj.ob_outlet, x->x_value);
1193}
1194
1195static void snapshot_tilde_set(t_snapshot *x, t_floatarg f)
1196{
1197 x->x_value = f;
1198}
1199
1200static void snapshot_tilde_setup(void)
1201{
1202 snapshot_tilde_class = class_new(gensym("snapshot~"), snapshot_tilde_new, 0,
1203 sizeof(t_snapshot), 0, 0);
1204 CLASS_MAINSIGNALIN(snapshot_tilde_class, t_snapshot, x_f);
1205 class_addmethod(snapshot_tilde_class, (t_method)snapshot_tilde_dsp,
1206 gensym("dsp"), 0);
1207 class_addmethod(snapshot_tilde_class, (t_method)snapshot_tilde_set,
1208 gensym("set"), A_DEFFLOAT, 0);
1209 class_addbang(snapshot_tilde_class, snapshot_tilde_bang);
1210}
1211
1212/* -------------------------- vsnapshot~ ------------------------------ */
1213static t_class *vsnapshot_tilde_class;
1214
1215typedef struct _vsnapshot
1216{
1217 t_object x_obj;
1218 int x_n;
1219 int x_gotone;
1220 t_sample *x_vec;
1221 float x_f;
1222 float x_sampspermsec;
1223 double x_time;
1224} t_vsnapshot;
1225
1226static void *vsnapshot_tilde_new(void)
1227{
1228 t_vsnapshot *x = (t_vsnapshot *)pd_new(vsnapshot_tilde_class);
1229 outlet_new(&x->x_obj, &s_float);
1230 x->x_f = 0;
1231 x->x_n = 0;
1232 x->x_vec = 0;
1233 x->x_gotone = 0;
1234 return (x);
1235}
1236
1237static t_int *vsnapshot_tilde_perform(t_int *w)
1238{
1239 t_float *in = (t_float *)(w[1]);
1240 t_vsnapshot *x = (t_vsnapshot *)(w[2]);
1241 t_float *out = x->x_vec;
1242 int n = x->x_n, i;
1243 for (i = 0; i < n; i++)
1244 out[i] = in[i];
1245 x->x_time = clock_getlogicaltime();
1246 x->x_gotone = 1;
1247 return (w+3);
1248}
1249
1250static void vsnapshot_tilde_dsp(t_vsnapshot *x, t_signal **sp)
1251{
1252 int n = sp[0]->s_n;
1253 if (n != x->x_n)
1254 {
1255 if (x->x_vec)
1256 t_freebytes(x->x_vec, x->x_n * sizeof(t_sample));
1257 x->x_vec = (t_sample *)getbytes(n * sizeof(t_sample));
1258 x->x_gotone = 0;
1259 x->x_n = n;
1260 }
1261 x->x_sampspermsec = sp[0]->s_sr / 1000;
1262 dsp_add(vsnapshot_tilde_perform, 2, sp[0]->s_vec, x);
1263}
1264
1265static void vsnapshot_tilde_bang(t_vsnapshot *x)
1266{
1267 float val;
1268 if (x->x_gotone)
1269 {
1270 int indx = clock_gettimesince(x->x_time) * x->x_sampspermsec;
1271 if (indx < 0)
1272 indx = 0;
1273 else if (indx >= x->x_n)
1274 indx = x->x_n - 1;
1275 val = x->x_vec[indx];
1276 }
1277 else val = 0;
1278 outlet_float(x->x_obj.ob_outlet, val);
1279}
1280
1281static void vsnapshot_tilde_ff(t_vsnapshot *x)
1282{
1283 if (x->x_vec)
1284 t_freebytes(x->x_vec, x->x_n * sizeof(t_sample));
1285}
1286
1287static void vsnapshot_tilde_setup(void)
1288{
1289 vsnapshot_tilde_class = class_new(gensym("vsnapshot~"),
1290 vsnapshot_tilde_new, (t_method)vsnapshot_tilde_ff,
1291 sizeof(t_vsnapshot), 0, 0);
1292 CLASS_MAINSIGNALIN(vsnapshot_tilde_class, t_vsnapshot, x_f);
1293 class_addmethod(vsnapshot_tilde_class, (t_method)vsnapshot_tilde_dsp, gensym("dsp"), 0);
1294 class_addbang(vsnapshot_tilde_class, vsnapshot_tilde_bang);
1295}
1296
1297
1298/* ---------------- env~ - simple envelope follower. ----------------- */
1299
1300#define MAXOVERLAP 10
1301#define MAXVSTAKEN 64
1302
1303typedef struct sigenv
1304{
1305 t_object x_obj; /* header */
1306 void *x_outlet; /* a "float" outlet */
1307 void *x_clock; /* a "clock" object */
1308 float *x_buf; /* a Hanning window */
1309 int x_phase; /* number of points since last output */
1310 int x_period; /* requested period of output */
1311 int x_realperiod; /* period rounded up to vecsize multiple */
1312 int x_npoints; /* analysis window size in samples */
1313 float x_result; /* result to output */
1314 float x_sumbuf[MAXOVERLAP]; /* summing buffer */
1315 float x_f;
1316} t_sigenv;
1317
1318t_class *env_tilde_class;
1319static void env_tilde_tick(t_sigenv *x);
1320
1321static void *env_tilde_new(t_floatarg fnpoints, t_floatarg fperiod)
1322{
1323 int npoints = fnpoints;
1324 int period = fperiod;
1325 t_sigenv *x;
1326 float *buf;
1327 int i;
1328
1329 if (npoints < 1) npoints = 1024;
1330 if (period < 1) period = npoints/2;
1331 if (period < npoints / MAXOVERLAP + 1)
1332 period = npoints / MAXOVERLAP + 1;
1333 if (!(buf = getbytes(sizeof(float) * (npoints + MAXVSTAKEN))))
1334 {
1335 error("env: couldn't allocate buffer");
1336 return (0);
1337 }
1338 x = (t_sigenv *)pd_new(env_tilde_class);
1339 x->x_buf = buf;
1340 x->x_npoints = npoints;
1341 x->x_phase = 0;
1342 x->x_period = period;
1343 for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0;
1344 for (i = 0; i < npoints; i++)
1345 buf[i] = (1. - cos((2 * 3.14159 * i) / npoints))/npoints;
1346 for (; i < npoints+MAXVSTAKEN; i++) buf[i] = 0;
1347 x->x_clock = clock_new(x, (t_method)env_tilde_tick);
1348 x->x_outlet = outlet_new(&x->x_obj, gensym("float"));
1349 x->x_f = 0;
1350 return (x);
1351}
1352
1353static t_int *env_tilde_perform(t_int *w)
1354{
1355 t_sigenv *x = (t_sigenv *)(w[1]);
1356 t_float *in = (t_float *)(w[2]);
1357 int n = (int)(w[3]);
1358 int count;
1359 float *sump;
1360 in += n;
1361 for (count = x->x_phase, sump = x->x_sumbuf;
1362 count < x->x_npoints; count += x->x_realperiod, sump++)
1363 {
1364 float *hp = x->x_buf + count;
1365 float *fp = in;
1366 float sum = *sump;
1367 int i;
1368
1369 for (i = 0; i < n; i++)
1370 {
1371 fp--;
1372 sum += *hp++ * (*fp * *fp);
1373 }
1374 *sump = sum;
1375 }
1376 sump[0] = 0;
1377 x->x_phase -= n;
1378 if (x->x_phase < 0)
1379 {
1380 x->x_result = x->x_sumbuf[0];
1381 for (count = x->x_realperiod, sump = x->x_sumbuf;
1382 count < x->x_npoints; count += x->x_realperiod, sump++)
1383 sump[0] = sump[1];
1384 sump[0] = 0;
1385 x->x_phase = x->x_realperiod - n;
1386 clock_delay(x->x_clock, 0L);
1387 }
1388 return (w+4);
1389}
1390
1391static void env_tilde_dsp(t_sigenv *x, t_signal **sp)
1392{
1393 if (x->x_period % sp[0]->s_n) x->x_realperiod =
1394 x->x_period + sp[0]->s_n - (x->x_period % sp[0]->s_n);
1395 else x->x_realperiod = x->x_period;
1396 dsp_add(env_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
1397 if (sp[0]->s_n > MAXVSTAKEN) bug("env_tilde_dsp");
1398}
1399
1400static void env_tilde_tick(t_sigenv *x) /* callback function for the clock */
1401{
1402 outlet_float(x->x_outlet, powtodb(x->x_result));
1403}
1404
1405static void env_tilde_ff(t_sigenv *x) /* cleanup on free */
1406{
1407 clock_free(x->x_clock);
1408 freebytes(x->x_buf, (x->x_npoints + MAXVSTAKEN) * sizeof(float));
1409}
1410
1411
1412void env_tilde_setup(void )
1413{
1414 env_tilde_class = class_new(gensym("env~"), (t_newmethod)env_tilde_new,
1415 (t_method)env_tilde_ff, sizeof(t_sigenv), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
1416 CLASS_MAINSIGNALIN(env_tilde_class, t_sigenv, x_f);
1417 class_addmethod(env_tilde_class, (t_method)env_tilde_dsp, gensym("dsp"), 0);
1418}
1419
1420/* --------------------- threshold~ ----------------------------- */
1421
1422static t_class *threshold_tilde_class;
1423
1424typedef struct _threshold_tilde
1425{
1426 t_object x_obj;
1427 t_outlet *x_outlet1; /* bang out for high thresh */
1428 t_outlet *x_outlet2; /* bang out for low thresh */
1429 t_clock *x_clock; /* wakeup for message output */
1430 float x_f; /* scalar inlet */
1431 int x_state; /* 1 = high, 0 = low */
1432 float x_hithresh; /* value of high threshold */
1433 float x_lothresh; /* value of low threshold */
1434 float x_deadwait; /* msec remaining in dead period */
1435 float x_msecpertick; /* msec per DSP tick */
1436 float x_hideadtime; /* hi dead time in msec */
1437 float x_lodeadtime; /* lo dead time in msec */
1438} t_threshold_tilde;
1439
1440static void threshold_tilde_tick(t_threshold_tilde *x);
1441static void threshold_tilde_set(t_threshold_tilde *x,
1442 t_floatarg hithresh, t_floatarg hideadtime,
1443 t_floatarg lothresh, t_floatarg lodeadtime);
1444
1445static t_threshold_tilde *threshold_tilde_new(t_floatarg hithresh,
1446 t_floatarg hideadtime, t_floatarg lothresh, t_floatarg lodeadtime)
1447{
1448 t_threshold_tilde *x = (t_threshold_tilde *)
1449 pd_new(threshold_tilde_class);
1450 x->x_state = 0; /* low state */
1451 x->x_deadwait = 0; /* no dead time */
1452 x->x_clock = clock_new(x, (t_method)threshold_tilde_tick);
1453 x->x_outlet1 = outlet_new(&x->x_obj, &s_bang);
1454 x->x_outlet2 = outlet_new(&x->x_obj, &s_bang);
1455 inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
1456 x->x_msecpertick = 0.;
1457 x->x_f = 0;
1458 threshold_tilde_set(x, hithresh, hideadtime, lothresh, lodeadtime);
1459 return (x);
1460}
1461
1462 /* "set" message to specify thresholds and dead times */
1463static void threshold_tilde_set(t_threshold_tilde *x,
1464 t_floatarg hithresh, t_floatarg hideadtime,
1465 t_floatarg lothresh, t_floatarg lodeadtime)
1466{
1467 if (lothresh > hithresh)
1468 lothresh = hithresh;
1469 x->x_hithresh = hithresh;
1470 x->x_hideadtime = hideadtime;
1471 x->x_lothresh = lothresh;
1472 x->x_lodeadtime = lodeadtime;
1473}
1474
1475 /* number in inlet sets state -- note incompatible with JMAX which used
1476 "int" message for this, impossible here because of auto signal conversion */
1477static void threshold_tilde_ft1(t_threshold_tilde *x, t_floatarg f)
1478{
1479 x->x_state = (f != 0);
1480 x->x_deadwait = 0;
1481}
1482
1483static void threshold_tilde_tick(t_threshold_tilde *x)
1484{
1485 if (x->x_state)
1486 outlet_bang(x->x_outlet1);
1487 else outlet_bang(x->x_outlet2);
1488}
1489
1490static t_int *threshold_tilde_perform(t_int *w)
1491{
1492 float *in1 = (float *)(w[1]);
1493 t_threshold_tilde *x = (t_threshold_tilde *)(w[2]);
1494 int n = (t_int)(w[3]);
1495 if (x->x_deadwait > 0)
1496 x->x_deadwait -= x->x_msecpertick;
1497 else if (x->x_state)
1498 {
1499 /* we're high; look for low sample */
1500 for (; n--; in1++)
1501 {
1502 if (*in1 < x->x_lothresh)
1503 {
1504 clock_delay(x->x_clock, 0L);
1505 x->x_state = 0;
1506 x->x_deadwait = x->x_lodeadtime;
1507 goto done;
1508 }
1509 }
1510 }
1511 else
1512 {
1513 /* we're low; look for high sample */
1514 for (; n--; in1++)
1515 {
1516 if (*in1 >= x->x_hithresh)
1517 {
1518 clock_delay(x->x_clock, 0L);
1519 x->x_state = 1;
1520 x->x_deadwait = x->x_hideadtime;
1521 goto done;
1522 }
1523 }
1524 }
1525done:
1526 return (w+4);
1527}
1528
1529void threshold_tilde_dsp(t_threshold_tilde *x, t_signal **sp)
1530{
1531 x->x_msecpertick = 1000. * sp[0]->s_n / sp[0]->s_sr;
1532 dsp_add(threshold_tilde_perform, 3, sp[0]->s_vec, x, sp[0]->s_n);
1533}
1534
1535static void threshold_tilde_ff(t_threshold_tilde *x)
1536{
1537 clock_free(x->x_clock);
1538}
1539
1540static void threshold_tilde_setup( void)
1541{
1542 threshold_tilde_class = class_new(gensym("threshold~"),
1543 (t_newmethod)threshold_tilde_new, (t_method)threshold_tilde_ff,
1544 sizeof(t_threshold_tilde), 0,
1545 A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
1546 CLASS_MAINSIGNALIN(threshold_tilde_class, t_threshold_tilde, x_f);
1547 class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_set,
1548 gensym("set"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
1549 class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_ft1,
1550 gensym("ft1"), A_FLOAT, 0);
1551 class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_dsp,
1552 gensym("dsp"), 0);
1553}
1554
1555/* ------------------------ global setup routine ------------------------- */
1556
1557void d_ctl_setup(void)
1558{
1559 sig_tilde_setup();
1560 line_tilde_setup();
1561 vline_tilde_setup();
1562 snapshot_tilde_setup();
1563 vsnapshot_tilde_setup();
1564 env_tilde_setup();
1565 threshold_tilde_setup();
1566}
1567
1568#endif