1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
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.
10
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.
15
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22 /*****************************************************************************
23 HISTORY
24 22/01/05 : added int cast in select2 and select3 selection signal
25 *****************************************************************************/
26
27 #include <float.h>
28 #include <vector>
29
30 #include "global.hh"
31 #include "ppsig.hh"
32 #include "signals.hh"
33 #include "xtended.hh"
34
sigWriteReadTable(Tree n,Tree init,Tree widx,Tree wsig,Tree ridx)35 EXPORT Tree sigWriteReadTable(Tree n, Tree init, Tree widx, Tree wsig, Tree ridx)
36 {
37 return sigRDTbl(sigWRTbl(gGlobal->nil, sigTable(gGlobal->nil, n, sigGen(init)), widx, wsig), ridx);
38 }
39
sigReadOnlyTable(Tree n,Tree init,Tree ridx)40 EXPORT Tree sigReadOnlyTable(Tree n, Tree init, Tree ridx)
41 {
42 return sigRDTbl(sigTable(gGlobal->nil, n, sigGen(init)), ridx);
43 }
44
45 ////////////////////////////////////////////////////////////////////////
46 /**
47 * Signals
48 */
49 ///////////////////////////////////////////////////////////////////////
50
sigRem(Tree x,Tree y)51 Tree sigRem(Tree x, Tree y)
52 {
53 if (isZero(y)) {
54 stringstream error;
55 error << "ERROR : % by 0 in " << ppsig(x) << " % " << ppsig(y) << endl;
56 throw faustexception(error.str());
57 }
58 return sigBinOp(kRem, x, y);
59 }
60
sigInt(int i)61 EXPORT Tree sigInt(int i)
62 {
63 return tree(i);
64 }
isSigInt(Tree t,int * i)65 bool isSigInt(Tree t, int* i)
66 {
67 return isInt(t->node(), i);
68 }
69
sigReal(double r)70 EXPORT Tree sigReal(double r)
71 {
72 return tree(r);
73 }
isSigReal(Tree t,double * r)74 bool isSigReal(Tree t, double* r)
75 {
76 return isDouble(t->node(), r);
77 }
78
sigInput(int i)79 EXPORT Tree sigInput(int i)
80 {
81 // Keep the max input number (used with the signal API)
82 gGlobal->gMaxInputs = std::max(gGlobal->gMaxInputs, i+1);
83 return tree(gGlobal->SIGINPUT, tree(i));
84 }
isSigInput(Tree t,int * i)85 bool isSigInput(Tree t, int* i)
86 {
87 Tree x;
88 return isTree(t, gGlobal->SIGINPUT, x) && isInt(x->node(), i);
89 }
90
sigOutput(int i,Tree t0)91 Tree sigOutput(int i, Tree t0)
92 {
93 return tree(gGlobal->SIGOUTPUT, tree(i), t0);
94 }
isSigOutput(Tree t,int * i,Tree & t0)95 bool isSigOutput(Tree t, int* i, Tree& t0)
96 {
97 Tree x;
98 return isTree(t, gGlobal->SIGOUTPUT, x, t0) && isInt(x->node(), i);
99 }
100
sigDelay0(Tree t0)101 Tree sigDelay0(Tree t0)
102 {
103 return sigDelay(t0, sigInt(0));
104 }
105
sigDelay1(Tree t0)106 Tree sigDelay1(Tree t0)
107 {
108 return tree(gGlobal->SIGDELAY1, t0);
109 }
isSigDelay1(Tree t,Tree & t0)110 bool isSigDelay1(Tree t, Tree& t0)
111 {
112 return isTree(t, gGlobal->SIGDELAY1, t0);
113 }
114
sigDelay(Tree t0,Tree t1)115 EXPORT Tree sigDelay(Tree t0, Tree t1)
116 {
117 return tree(gGlobal->SIGDELAY, t0, sigIntCast(t1));
118 }
isSigDelay(Tree t,Tree & t0,Tree & t1)119 bool isSigDelay(Tree t, Tree& t0, Tree& t1)
120 {
121 return isTree(t, gGlobal->SIGDELAY, t0, t1);
122 }
123
sigPrefix(Tree t0,Tree t1)124 Tree sigPrefix(Tree t0, Tree t1)
125 {
126 return tree(gGlobal->SIGPREFIX, t0, t1);
127 }
isSigPrefix(Tree t,Tree & t0,Tree & t1)128 bool isSigPrefix(Tree t, Tree& t0, Tree& t1)
129 {
130 return isTree(t, gGlobal->SIGPREFIX, t0, t1);
131 }
132
sigIota(Tree t0)133 Tree sigIota(Tree t0)
134 {
135 return tree(gGlobal->SIGIOTA, t0);
136 }
isSigIota(Tree t,Tree & t0)137 bool isSigIota(Tree t, Tree& t0)
138 {
139 return isTree(t, gGlobal->SIGIOTA, t0);
140 }
141
142 // Read only and read write tables
143
sigRDTbl(Tree t,Tree i)144 Tree sigRDTbl(Tree t, Tree i)
145 {
146 return tree(gGlobal->SIGRDTBL, t, i);
147 }
isSigRDTbl(Tree s,Tree & t,Tree & i)148 bool isSigRDTbl(Tree s, Tree& t, Tree& i)
149 {
150 return isTree(s, gGlobal->SIGRDTBL, t, i);
151 }
152
sigWRTbl(Tree id,Tree t,Tree i,Tree s)153 Tree sigWRTbl(Tree id, Tree t, Tree i, Tree s)
154 {
155 return tree(gGlobal->SIGWRTBL, id, t, i, s);
156 }
isSigWRTbl(Tree u,Tree & id,Tree & t,Tree & i,Tree & s)157 bool isSigWRTbl(Tree u, Tree& id, Tree& t, Tree& i, Tree& s)
158 {
159 return isTree(u, gGlobal->SIGWRTBL, id, t, i, s);
160 }
161
sigTable(Tree id,Tree n,Tree sig)162 Tree sigTable(Tree id, Tree n, Tree sig)
163 {
164 return tree(gGlobal->SIGTABLE, id, n, sig);
165 }
isSigTable(Tree t,Tree & id,Tree & n,Tree & sig)166 bool isSigTable(Tree t, Tree& id, Tree& n, Tree& sig)
167 {
168 return isTree(t, gGlobal->SIGTABLE, id, n, sig);
169 }
170
171 // Signal used to generate the initial content of a table
172
sigGen(Tree s)173 Tree sigGen(Tree s)
174 {
175 return tree(gGlobal->SIGGEN, s);
176 }
isSigGen(Tree t,Tree & x)177 bool isSigGen(Tree t, Tree& x)
178 {
179 return isTree(t, gGlobal->SIGGEN, x);
180 }
isSigGen(Tree t)181 bool isSigGen(Tree t)
182 {
183 return t->node() == Node(gGlobal->SIGGEN);
184 }
185
186 // Documentator Tables : special version of tables only for documentation purposes
187
sigDocConstantTbl(Tree n,Tree sig)188 Tree sigDocConstantTbl(Tree n, Tree sig)
189 {
190 return tree(gGlobal->SIGDOCONSTANTTBL, n, sig);
191 }
isSigDocConstantTbl(Tree t,Tree & n,Tree & sig)192 bool isSigDocConstantTbl(Tree t, Tree& n, Tree& sig)
193 {
194 return isTree(t, gGlobal->SIGDOCONSTANTTBL, n, sig);
195 }
196
sigDocWriteTbl(Tree n,Tree sig,Tree widx,Tree wsig)197 Tree sigDocWriteTbl(Tree n, Tree sig, Tree widx, Tree wsig)
198 {
199 return tree(gGlobal->SIGDOCWRITETBL, n, sig, widx, wsig);
200 }
isSigDocWriteTbl(Tree t,Tree & n,Tree & sig,Tree & widx,Tree & wsig)201 bool isSigDocWriteTbl(Tree t, Tree& n, Tree& sig, Tree& widx, Tree& wsig)
202 {
203 return isTree(t, gGlobal->SIGDOCWRITETBL, n, sig, widx, wsig);
204 }
205
sigDocAccessTbl(Tree tbl,Tree ridx)206 Tree sigDocAccessTbl(Tree tbl, Tree ridx)
207 {
208 return tree(gGlobal->SIGDOCACCESSTBL, tbl, ridx);
209 }
isSigDocAccessTbl(Tree t,Tree & tbl,Tree & ridx)210 bool isSigDocAccessTbl(Tree t, Tree& tbl, Tree& ridx)
211 {
212 return isTree(t, gGlobal->SIGDOCACCESSTBL, tbl, ridx);
213 }
214
215 // Select on signal among severals
216
sigSelect2(Tree selector,Tree s1,Tree s2)217 EXPORT Tree sigSelect2(Tree selector, Tree s1, Tree s2)
218 {
219 return tree(gGlobal->SIGSELECT2, sigIntCast(selector), s1, s2);
220 }
isSigSelect2(Tree t,Tree & selector,Tree & s1,Tree & s2)221 bool isSigSelect2(Tree t, Tree& selector, Tree& s1, Tree& s2)
222 {
223 return isTree(t, gGlobal->SIGSELECT2, selector, s1, s2);
224 }
225
226 // "select3" expressed with "select2"
sigSelect3(Tree selector,Tree s1,Tree s2,Tree s3)227 EXPORT Tree sigSelect3(Tree selector, Tree s1, Tree s2, Tree s3)
228 {
229 return sigSelect2(sigBinOp(kEQ, sigIntCast(selector), sigInt(0)),
230 sigSelect2(sigBinOp(kEQ, sigIntCast(selector), sigInt(1)), s3, s2), s1);
231 }
232
sigAssertBounds(Tree s1,Tree s2,Tree s3)233 Tree sigAssertBounds(Tree s1, Tree s2, Tree s3)
234 {
235 return tree(gGlobal->SIGASSERTBOUNDS, s1, s2, s3);
236 }
237
isSigAssertBounds(Tree t,Tree & s1,Tree & s2,Tree & s3)238 bool isSigAssertBounds(Tree t, Tree& s1, Tree& s2, Tree& s3)
239 {
240 return isTree(t, gGlobal->SIGASSERTBOUNDS, s1, s2, s3);
241 }
242
sigHighest(Tree s)243 Tree sigHighest(Tree s)
244 {
245 return tree(gGlobal->SIGHIGHEST, s);
246 }
247
isSigHighest(Tree t,Tree & s)248 bool isSigHighest(Tree t, Tree& s)
249 {
250 return isTree(t, gGlobal->SIGHIGHEST, s);
251 }
252
sigLowest(Tree s)253 Tree sigLowest(Tree s)
254 {
255 return tree(gGlobal->SIGLOWEST, s);
256 }
257
isSigLowest(Tree t,Tree & s)258 bool isSigLowest(Tree t, Tree& s)
259 {
260 return isTree(t, gGlobal->SIGLOWEST, s);
261 }
262
263 // Arithmetical operations
264
sigBinOp(int op,Tree x,Tree y)265 EXPORT Tree sigBinOp(int op, Tree x, Tree y)
266 {
267 return tree(gGlobal->SIGBINOP, tree(op), x, y);
268 }
isSigBinOp(Tree s,int * op,Tree & x,Tree & y)269 bool isSigBinOp(Tree s, int* op, Tree& x, Tree& y)
270 {
271 Tree t;
272 return isTree(s, gGlobal->SIGBINOP, t, x, y) && isInt(t->node(), op);
273 }
274
275 // Foreign Functions
276
sigFFun(Tree ff,Tree largs)277 Tree sigFFun(Tree ff, Tree largs)
278 {
279 return tree(gGlobal->SIGFFUN, ff, largs);
280 }
isSigFFun(Tree s,Tree & ff,Tree & largs)281 bool isSigFFun(Tree s, Tree& ff, Tree& largs)
282 {
283 return isTree(s, gGlobal->SIGFFUN, ff, largs);
284 }
285
sigFConst(Tree type,Tree name,Tree file)286 EXPORT Tree sigFConst(Tree type, Tree name, Tree file)
287 {
288 return tree(gGlobal->SIGFCONST, type, name, file);
289 }
isSigFConst(Tree s)290 bool isSigFConst(Tree s)
291 {
292 Tree t, n, f;
293 return isTree(s, gGlobal->SIGFCONST, t, n, f);
294 }
isSigFConst(Tree s,Tree & type,Tree & name,Tree & file)295 bool isSigFConst(Tree s, Tree& type, Tree& name, Tree& file)
296 {
297 return isTree(s, gGlobal->SIGFCONST, type, name, file);
298 }
299
sigFVar(Tree type,Tree name,Tree file)300 EXPORT Tree sigFVar(Tree type, Tree name, Tree file)
301 {
302 return tree(gGlobal->SIGFVAR, type, name, file);
303 }
isSigFVar(Tree s)304 bool isSigFVar(Tree s)
305 {
306 Tree t, n, f;
307 return isTree(s, gGlobal->SIGFVAR, t, n, f);
308 }
isSigFVar(Tree s,Tree & type,Tree & name,Tree & file)309 bool isSigFVar(Tree s, Tree& type, Tree& name, Tree& file)
310 {
311 return isTree(s, gGlobal->SIGFVAR, type, name, file);
312 }
313
314 // New version using rec and ref
315
sigProj(int i,Tree rgroup)316 Tree sigProj(int i, Tree rgroup)
317 {
318 return tree(gGlobal->SIGPROJ, tree(i), rgroup);
319 }
isProj(Tree t,int * i,Tree & rgroup)320 bool isProj(Tree t, int* i, Tree& rgroup)
321 {
322 Tree x;
323 return isTree(t, gGlobal->SIGPROJ, x, rgroup) && isInt(x->node(), i);
324 }
325
326 // Int and Float casting
327
sigIntCast(Tree t)328 EXPORT Tree sigIntCast(Tree t)
329 {
330 Node n = t->node();
331
332 int i;
333 if (isInt(n, &i)) return t;
334 double x;
335 if (isDouble(n, &x)) return tree(int(x));
336 if (isSigIntCast(t)) return t;
337
338 return tree(gGlobal->SIGINTCAST, t);
339 }
340
sigFloatCast(Tree t)341 EXPORT Tree sigFloatCast(Tree t)
342 {
343 // cerr << "sigFloatCast(" << ppsig(t) << ")" << endl;
344 Node n = t->node();
345
346 int i;
347 if (isInt(n, &i)) return tree(double(i));
348 double x;
349 if (isDouble(n, &x)) return t;
350 if (isSigFloatCast(t)) return t;
351 if (isSigInput(t, &i)) return t;
352
353 return tree(gGlobal->SIGFLOATCAST, t);
354 }
355
356 // Tree sigFloatCast(Tree t) { return isSigFloatCast(t)? t : tree(gGlobal->SIGFLOATCAST, t); }
357
isSigIntCast(Tree t)358 bool isSigIntCast(Tree t)
359 {
360 Tree x;
361 return isTree(t, gGlobal->SIGINTCAST, x);
362 }
isSigIntCast(Tree t,Tree & x)363 bool isSigIntCast(Tree t, Tree& x)
364 {
365 return isTree(t, gGlobal->SIGINTCAST, x);
366 }
367
isSigFloatCast(Tree t)368 bool isSigFloatCast(Tree t)
369 {
370 Tree x;
371 return isTree(t, gGlobal->SIGFLOATCAST, x);
372 }
isSigFloatCast(Tree t,Tree & x)373 bool isSigFloatCast(Tree t, Tree& x)
374 {
375 return isTree(t, gGlobal->SIGFLOATCAST, x);
376 }
377
378 // Emulation of all fonctions
sigAdd(Tree x,Tree y)379 EXPORT Tree sigAdd(Tree x, Tree y)
380 {
381 return sigBinOp(kAdd, x, y);
382 }
sigSub(Tree x,Tree y)383 EXPORT Tree sigSub(Tree x, Tree y)
384 {
385 return sigBinOp(kSub, x, y);
386 }
sigMul(Tree x,Tree y)387 EXPORT Tree sigMul(Tree x, Tree y)
388 {
389 return sigBinOp(kMul, x, y);
390 }
sigDiv(Tree x,Tree y)391 EXPORT Tree sigDiv(Tree x, Tree y)
392 {
393 return sigBinOp(kDiv, x, y);
394 }
395 Tree sigRem(Tree x, Tree y);
396
sigAND(Tree x,Tree y)397 EXPORT Tree sigAND(Tree x, Tree y)
398 {
399 return sigBinOp(kAND, x, y);
400 }
sigOR(Tree x,Tree y)401 EXPORT Tree sigOR(Tree x, Tree y)
402 {
403 return sigBinOp(kOR, x, y);
404 }
sigXOR(Tree x,Tree y)405 EXPORT Tree sigXOR(Tree x, Tree y)
406 {
407 return sigBinOp(kXOR, x, y);
408 }
409
sigLeftShift(Tree x,Tree y)410 EXPORT Tree sigLeftShift(Tree x, Tree y)
411 {
412 return sigBinOp(kLsh, x, y);
413 }
sigARightShift(Tree x,Tree y)414 EXPORT Tree sigARightShift(Tree x, Tree y)
415 {
416 return sigBinOp(kARsh, x, y);
417 }
sigLRightShift(Tree x,Tree y)418 EXPORT Tree sigLRightShift(Tree x, Tree y)
419 {
420 return sigBinOp(kLRsh, x, y);
421 }
422
sigGT(Tree x,Tree y)423 EXPORT Tree sigGT(Tree x, Tree y)
424 {
425 return sigBinOp(kGT, x, y);
426 }
sigLT(Tree x,Tree y)427 EXPORT Tree sigLT(Tree x, Tree y)
428 {
429 return sigBinOp(kLT, x, y);
430 }
sigGE(Tree x,Tree y)431 EXPORT Tree sigGE(Tree x, Tree y)
432 {
433 return sigBinOp(kGE, x, y);
434 }
sigLE(Tree x,Tree y)435 EXPORT Tree sigLE(Tree x, Tree y)
436 {
437 return sigBinOp(kLE, x, y);
438 }
sigEQ(Tree x,Tree y)439 EXPORT Tree sigEQ(Tree x, Tree y)
440 {
441 return sigBinOp(kEQ, x, y);
442 }
sigNE(Tree x,Tree y)443 EXPORT Tree sigNE(Tree x, Tree y)
444 {
445 return sigBinOp(kNE, x, y);
446 }
447
448 /*****************************************************************************
449 User Interface Elements
450 *****************************************************************************/
451
sigButton(Tree lbl)452 EXPORT Tree sigButton(Tree lbl)
453 {
454 return tree(gGlobal->SIGBUTTON, lbl);
455 }
isSigButton(Tree s)456 bool isSigButton(Tree s)
457 {
458 Tree lbl;
459 return isTree(s, gGlobal->SIGBUTTON, lbl);
460 }
isSigButton(Tree s,Tree & lbl)461 bool isSigButton(Tree s, Tree& lbl)
462 {
463 return isTree(s, gGlobal->SIGBUTTON, lbl);
464 }
465
sigCheckbox(Tree lbl)466 EXPORT Tree sigCheckbox(Tree lbl)
467 {
468 return tree(gGlobal->SIGCHECKBOX, lbl);
469 }
isSigCheckbox(Tree s)470 bool isSigCheckbox(Tree s)
471 {
472 Tree lbl;
473 return isTree(s, gGlobal->SIGCHECKBOX, lbl);
474 }
isSigCheckbox(Tree s,Tree & lbl)475 bool isSigCheckbox(Tree s, Tree& lbl)
476 {
477 return isTree(s, gGlobal->SIGCHECKBOX, lbl);
478 }
479
sigWaveform(const tvec & wf)480 EXPORT Tree sigWaveform(const tvec& wf)
481 {
482 return tree(gGlobal->SIGWAVEFORM, wf);
483 }
isSigWaveform(Tree s)484 bool isSigWaveform(Tree s)
485 {
486 return isTree(s, gGlobal->SIGWAVEFORM);
487 }
488
sigHSlider(Tree lbl,Tree init,Tree min,Tree max,Tree step)489 EXPORT Tree sigHSlider(Tree lbl, Tree init, Tree min, Tree max, Tree step)
490 {
491 return tree(gGlobal->SIGHSLIDER, lbl, list4(init, min, max, step));
492 }
isSigHSlider(Tree s)493 bool isSigHSlider(Tree s)
494 {
495 Tree lbl, params;
496 return isTree(s, gGlobal->SIGHSLIDER, lbl, params);
497 }
498
isSigHSlider(Tree s,Tree & lbl,Tree & init,Tree & min,Tree & max,Tree & step)499 bool isSigHSlider(Tree s, Tree& lbl, Tree& init, Tree& min, Tree& max, Tree& step)
500 {
501 Tree params;
502 if (isTree(s, gGlobal->SIGHSLIDER, lbl, params)) {
503 init = nth(params, 0);
504 min = nth(params, 1);
505 max = nth(params, 2);
506 step = nth(params, 3);
507 return true;
508 } else {
509 return false;
510 }
511 }
512
sigVSlider(Tree lbl,Tree init,Tree min,Tree max,Tree step)513 EXPORT Tree sigVSlider(Tree lbl, Tree init, Tree min, Tree max, Tree step)
514 {
515 return tree(gGlobal->SIGVSLIDER, lbl, list4(init, min, max, step));
516 }
isSigVSlider(Tree s)517 bool isSigVSlider(Tree s)
518 {
519 Tree lbl, params;
520 return isTree(s, gGlobal->SIGVSLIDER, lbl, params);
521 }
522
isSigVSlider(Tree s,Tree & lbl,Tree & init,Tree & min,Tree & max,Tree & step)523 bool isSigVSlider(Tree s, Tree& lbl, Tree& init, Tree& min, Tree& max, Tree& step)
524 {
525 Tree params;
526 if (isTree(s, gGlobal->SIGVSLIDER, lbl, params)) {
527 init = nth(params, 0);
528 min = nth(params, 1);
529 max = nth(params, 2);
530 step = nth(params, 3);
531 return true;
532 } else {
533 return false;
534 }
535 }
536
sigNumEntry(Tree lbl,Tree init,Tree min,Tree max,Tree step)537 EXPORT Tree sigNumEntry(Tree lbl, Tree init, Tree min, Tree max, Tree step)
538 {
539 return tree(gGlobal->SIGNUMENTRY, lbl, list4(init, min, max, step));
540 }
isSigNumEntry(Tree s)541 bool isSigNumEntry(Tree s)
542 {
543 Tree lbl, params;
544 return isTree(s, gGlobal->SIGNUMENTRY, lbl, params);
545 }
546
isSigNumEntry(Tree s,Tree & lbl,Tree & init,Tree & min,Tree & max,Tree & step)547 bool isSigNumEntry(Tree s, Tree& lbl, Tree& init, Tree& min, Tree& max, Tree& step)
548 {
549 Tree params;
550 if (isTree(s, gGlobal->SIGNUMENTRY, lbl, params)) {
551 init = nth(params, 0);
552 min = nth(params, 1);
553 max = nth(params, 2);
554 step = nth(params, 3);
555 return true;
556 } else {
557 return false;
558 }
559 }
560
561 // Output elements
562
sigHBargraph(Tree lbl,Tree min,Tree max,Tree x)563 EXPORT Tree sigHBargraph(Tree lbl, Tree min, Tree max, Tree x)
564 {
565 return tree(gGlobal->SIGHBARGRAPH, lbl, min, max, x);
566 }
isSigHBargraph(Tree s)567 bool isSigHBargraph(Tree s)
568 {
569 Tree lbl, min, max, x;
570 return isTree(s, gGlobal->SIGHBARGRAPH, lbl, min, max, x);
571 }
isSigHBargraph(Tree s,Tree & lbl,Tree & min,Tree & max,Tree & x)572 bool isSigHBargraph(Tree s, Tree& lbl, Tree& min, Tree& max, Tree& x)
573 {
574 return isTree(s, gGlobal->SIGHBARGRAPH, lbl, min, max, x);
575 }
576
sigVBargraph(Tree lbl,Tree min,Tree max,Tree x)577 EXPORT Tree sigVBargraph(Tree lbl, Tree min, Tree max, Tree x)
578 {
579 return tree(gGlobal->SIGVBARGRAPH, lbl, min, max, x);
580 }
isSigVBargraph(Tree s)581 bool isSigVBargraph(Tree s)
582 {
583 Tree lbl, min, max, x;
584 return isTree(s, gGlobal->SIGVBARGRAPH, lbl, min, max, x);
585 }
isSigVBargraph(Tree s,Tree & lbl,Tree & min,Tree & max,Tree & x)586 bool isSigVBargraph(Tree s, Tree& lbl, Tree& min, Tree& max, Tree& x)
587 {
588 return isTree(s, gGlobal->SIGVBARGRAPH, lbl, min, max, x);
589 }
590
sigAttach(Tree t0,Tree t1)591 Tree sigAttach(Tree t0, Tree t1)
592 {
593 return tree(gGlobal->SIGATTACH, t0, t1);
594 }
isSigAttach(Tree t,Tree & t0,Tree & t1)595 bool isSigAttach(Tree t, Tree& t0, Tree& t1)
596 {
597 return isTree(t, gGlobal->SIGATTACH, t0, t1);
598 }
599
sigEnable(Tree t0,Tree t1)600 Tree sigEnable(Tree t0, Tree t1)
601 {
602 return tree(gGlobal->SIGENABLE, t0, t1);
603 }
isSigEnable(Tree t,Tree & t0,Tree & t1)604 bool isSigEnable(Tree t, Tree& t0, Tree& t1)
605 {
606 return isTree(t, gGlobal->SIGENABLE, t0, t1);
607 }
608
sigControl(Tree t0,Tree t1)609 Tree sigControl(Tree t0, Tree t1)
610 {
611 return tree(gGlobal->SIGCONTROL, t0, t1);
612 }
isSigControl(Tree t,Tree & t0,Tree & t1)613 bool isSigControl(Tree t, Tree& t0, Tree& t1)
614 {
615 return isTree(t, gGlobal->SIGCONTROL, t0, t1);
616 }
617
618 // Extended math functions
sigExtended1(Tree sig,Tree x)619 static Tree sigExtended1(Tree sig, Tree x)
620 {
621 tvec args;
622 args.push_back(x);
623 return ((xtended*)getUserData(sig))->computeSigOutput(args);
624 }
625
sigExtended2(Tree sig,Tree x,Tree y)626 static Tree sigExtended2(Tree sig, Tree x, Tree y)
627 {
628 tvec args;
629 args.push_back(x);
630 args.push_back(y);
631 return ((xtended*)getUserData(sig))->computeSigOutput(args);
632 }
633
sigAbs(Tree x)634 EXPORT Tree sigAbs(Tree x)
635 {
636 return sigExtended1(gGlobal->gAbsPrim->box(), x);
637 }
638
sigAcos(Tree x)639 EXPORT Tree sigAcos(Tree x)
640 {
641 return sigExtended1(gGlobal->gAcosPrim->box(), x);
642 }
643
sigTan(Tree x)644 EXPORT Tree sigTan(Tree x)
645 {
646 return sigExtended1(gGlobal->gTanPrim->box(), x);
647 }
648
sigSqrt(Tree x)649 EXPORT Tree sigSqrt(Tree x)
650 {
651 return sigExtended1(gGlobal->gSqrtPrim->box(), x);
652 }
653
sigSin(Tree x)654 EXPORT Tree sigSin(Tree x)
655 {
656 return sigExtended1(gGlobal->gSinPrim->box(), x);
657 }
658
sigRint(Tree x)659 EXPORT Tree sigRint(Tree x)
660 {
661 return sigExtended1(gGlobal->gRintPrim->box(), x);
662 }
663
sigRemainder(Tree x,Tree y)664 EXPORT Tree sigRemainder(Tree x, Tree y)
665 {
666 return sigExtended2(gGlobal->gRemainderPrim->box(), x, y);
667 }
668
sigPow(Tree x,Tree y)669 EXPORT Tree sigPow(Tree x, Tree y)
670 {
671 return sigExtended2(gGlobal->gPowPrim->box(), x, y);
672 }
673
sigMin(Tree x,Tree y)674 EXPORT Tree sigMin(Tree x, Tree y)
675 {
676 return sigExtended2(gGlobal->gMinPrim->box(), x, y);
677 }
678
sigMax(Tree x,Tree y)679 EXPORT Tree sigMax(Tree x, Tree y)
680 {
681 return sigExtended2(gGlobal->gMaxPrim->box(), x, y);
682 }
683
sigLog(Tree x)684 EXPORT Tree sigLog(Tree x)
685 {
686 return sigExtended1(gGlobal->gLogPrim->box(), x);
687 }
688
sigLog10(Tree x)689 EXPORT Tree sigLog10(Tree x)
690 {
691 return sigExtended1(gGlobal->gLog10Prim->box(), x);
692 }
693
sigFmod(Tree x,Tree y)694 EXPORT Tree sigFmod(Tree x, Tree y)
695 {
696 return sigExtended2(gGlobal->gFmodPrim->box(), x, y);
697 }
698
sigFloor(Tree x)699 EXPORT Tree sigFloor(Tree x)
700 {
701 return sigExtended1(gGlobal->gFloorPrim->box(), x);
702 }
703
sigExp(Tree x)704 EXPORT Tree sigExp(Tree x)
705 {
706 return sigExtended1(gGlobal->gExpPrim->box(), x);
707 }
708
sigExp10(Tree x)709 EXPORT Tree sigExp10(Tree x)
710 {
711 return sigExtended1(gGlobal->gExp10Prim->box(), x);
712 }
713
sigCos(Tree x)714 EXPORT Tree sigCos(Tree x)
715 {
716 return sigExtended1(gGlobal->gCosPrim->box(), x);
717 }
718
sigCeil(Tree x)719 EXPORT Tree sigCeil(Tree x)
720 {
721 return sigExtended1(gGlobal->gCeilPrim->box(), x);
722 }
723
sigAtan(Tree x)724 EXPORT Tree sigAtan(Tree x)
725 {
726 return sigExtended1(gGlobal->gAtanPrim->box(), x);
727 }
728
sigAtan2(Tree x,Tree y)729 EXPORT Tree sigAtan2(Tree x, Tree y)
730 {
731 return sigExtended2(gGlobal->gAtan2Prim->box(), x, y);
732 }
733
sigAsin(Tree x)734 EXPORT Tree sigAsin(Tree x)
735 {
736 return sigExtended1(gGlobal->gAsinPrim->box(), x);
737 }
738
sameMagnitude(Tree a,Tree b)739 bool sameMagnitude(Tree a, Tree b)
740 {
741 return sameMagnitude(a->node(), b->node());
742 }
743
addNums(Tree a,Tree b)744 Tree addNums(Tree a, Tree b)
745 {
746 Tree r = tree(addNode(a->node(), b->node()));
747 // cerr.flags(ios::showpoint); cerr << "addNums " << *a << "+" << *b << " -> " << *r << endl;
748 return r;
749 }
750
subNums(Tree a,Tree b)751 Tree subNums(Tree a, Tree b)
752 {
753 Tree r = tree(subNode(a->node(), b->node()));
754 // cerr.flags(ios::showpoint); cerr << "subNums " << *a << "-" << *b << " -> " << *r << endl;
755 return r;
756 }
757
mulNums(Tree a,Tree b)758 Tree mulNums(Tree a, Tree b)
759 {
760 Tree r = tree(mulNode(a->node(), b->node()));
761 // cerr.flags(ios::showpoint); cerr << "mulNums " << *a << "*" << *b << " -> " << *r << endl;
762 return r;
763 }
764
765 // Tree divNums(Tree a, Tree b)
766 //{
767 // Tree r = tree(divNode(a->node(),b->node()));
768 // //cerr.flags(ios::showpoint); cerr << "divNums " << *a << "/" << *b << " -> " << *r << endl;
769 // return r;
770 //}
771
divExtendedNums(Tree a,Tree b)772 Tree divExtendedNums(Tree a, Tree b)
773 {
774 // cerr.flags(ios::showpoint); cerr << "divExtendeNums " << *a << "/" << *b << " -> " << endl;
775 Tree r = tree(divExtendedNode(a->node(), b->node()));
776 // cerr.flags(ios::showpoint); cerr << "divExtendeNums " << *a << "/" << *b << " -> " << *r << endl;
777 return r;
778 }
779
minusNum(Tree a)780 Tree minusNum(Tree a)
781 {
782 Tree r = tree(minusNode(a->node()));
783 // cerr.flags(ios::showpoint); cerr << "minusNum " << *a << " -> " << *r << endl;
784 return r;
785 }
786
inverseNum(Tree a)787 Tree inverseNum(Tree a)
788 {
789 Tree r = tree(inverseNode(a->node()));
790 // cerr.flags(ios::showpoint); cerr << "inverseNum " << *a << " -> " << *r << endl;
791 return r;
792 }
793
isSigAdd(Tree a,Tree & x,Tree & y)794 bool isSigAdd(Tree a, Tree& x, Tree& y)
795 {
796 int op;
797 return isSigBinOp(a, &op, x, y) && (op == kAdd);
798 }
799
isSigMul(Tree a,Tree & x,Tree & y)800 bool isSigMul(Tree a, Tree& x, Tree& y)
801 {
802 int op;
803 return isSigBinOp(a, &op, x, y) && (op == kMul);
804 }
805
isSigSub(Tree a,Tree & x,Tree & y)806 bool isSigSub(Tree a, Tree& x, Tree& y)
807 {
808 int op;
809 return isSigBinOp(a, &op, x, y) && (op == kSub);
810 }
811
isSigDiv(Tree a,Tree & x,Tree & y)812 bool isSigDiv(Tree a, Tree& x, Tree& y)
813 {
814 int op;
815 return isSigBinOp(a, &op, x, y) && (op == kDiv);
816 }
817
818 /*****************************************************************************
819 Soundfiles
820 *****************************************************************************/
821 /*
822 A boxSoundfile(label,c) has 2 inputs and c+3 outputs:
823 0 sigSoundfileLength(label, part): the number of frames of the soundfile part (NK)
824 1 sigSoundfileRate(label, part): the sampling rate encoded in the file (NK)
825 2 sigSoundfileBuffer(label, c, part, ridx): the cth channel content (RK ou RS)
826 */
sigSoundfile(Tree label)827 EXPORT Tree sigSoundfile(Tree label)
828 {
829 return tree(gGlobal->SIGSOUNDFILE, label);
830 }
sigSoundfileLength(Tree sf,Tree part)831 EXPORT Tree sigSoundfileLength(Tree sf, Tree part)
832 {
833 return tree(gGlobal->SIGSOUNDFILELENGTH, sf, part);
834 }
sigSoundfileRate(Tree sf,Tree part)835 EXPORT Tree sigSoundfileRate(Tree sf, Tree part)
836 {
837 return tree(gGlobal->SIGSOUNDFILERATE, sf, part);
838 }
sigSoundfileBuffer(Tree sf,Tree chan,Tree part,Tree ridx)839 EXPORT Tree sigSoundfileBuffer(Tree sf, Tree chan, Tree part, Tree ridx)
840 {
841 return tree(gGlobal->SIGSOUNDFILEBUFFER, sf, chan, part, ridx);
842 }
843
isSigSoundfile(Tree s,Tree & label)844 bool isSigSoundfile(Tree s, Tree& label)
845 {
846 return isTree(s, gGlobal->SIGSOUNDFILE, label);
847 }
isSigSoundfileLength(Tree s,Tree & sf,Tree & part)848 bool isSigSoundfileLength(Tree s, Tree& sf, Tree& part)
849 {
850 return isTree(s, gGlobal->SIGSOUNDFILELENGTH, sf, part);
851 }
isSigSoundfileRate(Tree s,Tree & sf,Tree & part)852 bool isSigSoundfileRate(Tree s, Tree& sf, Tree& part)
853 {
854 return isTree(s, gGlobal->SIGSOUNDFILERATE, sf, part);
855 }
isSigSoundfileBuffer(Tree s,Tree & sf,Tree & chan,Tree & part,Tree & ridx)856 bool isSigSoundfileBuffer(Tree s, Tree& sf, Tree& chan, Tree& part, Tree& ridx)
857 {
858 return isTree(s, gGlobal->SIGSOUNDFILEBUFFER, sf, chan, part, ridx);
859 }
860 /*****************************************************************************
861 matrix extension
862 *****************************************************************************/
863
864 // a tuple of signals is basically a list of signals.
865 // mode = 0 means normal, mode = 1 means blocked
sigTuple(int mode,Tree ls)866 Tree sigTuple(int mode, Tree ls)
867 {
868 return tree(gGlobal->SIGTUPLE, tree(mode), ls);
869 }
isSigTuple(Tree s,int * mode,Tree & ls)870 bool isSigTuple(Tree s, int* mode, Tree& ls)
871 {
872 Tree m;
873 return isTree(s, gGlobal->SIGTUPLE, m, ls) && isInt(m->node(), mode);
874 }
875
876 // Access the components of a tuple.
877 // ts is tuple of signals, idx is a scalar signal between 0..n
sigTupleAccess(Tree ts,Tree idx)878 Tree sigTupleAccess(Tree ts, Tree idx)
879 {
880 return tree(gGlobal->SIGTUPLEACCESS, ts, idx);
881 }
isSigTupleAccess(Tree s,Tree & ts,Tree & idx)882 bool isSigTupleAccess(Tree s, Tree& ts, Tree& idx)
883 {
884 return isTree(s, gGlobal->SIGTUPLEACCESS, ts, idx);
885 }
886
887 // create a tuple of signals
sigCartesianProd(Tree s1,Tree s2)888 Tree sigCartesianProd(Tree s1, Tree s2)
889 {
890 Tree l1, l2;
891 int m1, m2;
892
893 if (isSigTuple(s1, &m1, l1) && (m1 == 0)) {
894 // nothing to do
895 } else {
896 l1 = list1(s1);
897 }
898
899 if (isSigTuple(s2, &m2, l2) && (m2 == 0)) {
900 // nothing to do
901 } else {
902 l2 = list1(s2);
903 }
904
905 return sigTuple(0, concat(l1, l2));
906 }
907
908 /**
909 * Test if exp is very simple that is it
910 * can't be considered a real component
911 * @param exp the signal we want to test
912 * @return true if it a very simple signal
913 */
verySimple(Tree exp)914 bool verySimple(Tree exp)
915 {
916 int i;
917 double r;
918 Tree type, name, file;
919
920 return isSigInt(exp, &i) || isSigReal(exp, &r) || isSigInput(exp, &i) || isSigFConst(exp, type, name, file);
921 }
922
923 /*****************************************************************************
924 FTZ wrapping
925 Add FTZ wrapping to a signal
926 *****************************************************************************/
927
928 // \(x).(select2(abs(x)<mmm, x, 0))
929
sigFTZ(Tree s)930 Tree sigFTZ(Tree s)
931 {
932 return tree(gGlobal->gFtzPrim->symbol(), s);
933 }
934
935 /*****************************************************************************
936 * sigList2vectInt
937 *****************************************************************************/
938 // Convert a list of signals (representing numbers) into a vector of ints
939 // the result is true if the conversion was possible
940
sigList2vecInt(Tree ls,vector<int> & v)941 bool sigList2vecInt(Tree ls, vector<int>& v)
942 {
943 int i;
944 double x;
945
946 while (!isNil(ls)) {
947 Tree s = hd(ls);
948 ls = tl(ls);
949 if (isSigInt(s, &i)) {
950 v.push_back(i);
951 } else if (isSigReal(s, &x)) {
952 v.push_back(int(x));
953 } else {
954 return false;
955 }
956 }
957 return true;
958 }
959
960 /**
961 * Convert an stl vector of signals into a tree list of signals
962 */
listConvert(const siglist & a)963 Tree listConvert(const siglist& a)
964 {
965 int n = (int)a.size();
966 Tree t = gGlobal->nil;
967
968 while (n--) t = cons(a[n], t);
969 return t;
970 }
971