1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
5
6
7 Emil Post Tag Sytem UGens
8 by Julian Rohrhuber
9
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "SC_PlugIn.h"
27 #include <stdio.h>
28
29 #ifndef MAXFLOAT
30 # include <float.h>
31 # define MAXFLOAT FLT_MAX
32 #endif
33
34 static InterfaceTable *ft;
35
36 #define MAXCHANNELS 32
37
38
39 struct DbufTag : public Unit
40 {
41 float m_fbufnum;
42 SndBuf *m_buf;
43 int *m_rule_offsets;
44 int *m_rule_lengths;
45 int32 m_axiom_size; // all these int32 could be uint32, but sc_wrap would need support for this.
46 int32 m_read_pos;
47 int32 m_write_pos;
48 int m_numRules;
49 };
50
51 struct Dtag : public Unit
52 {
53 int *m_rule_offsets;
54 int *m_rule_lengths;
55 float *m_tape;
56 int32 m_tape_size;
57 int32 m_axiom_size;
58 int32 m_read_pos;
59 int32 m_write_pos;
60 int m_numRules;
61 };
62
63
64 extern "C"
65 {
66 void DbufTag_Ctor(DbufTag *unit);
67 void DbufTag_Dtor(DbufTag *unit);
68 void DbufTag_next(DbufTag *unit, int inNumSamples);
69
70 void Dtag_Ctor(Dtag *unit);
71 void Dtag_Dtor(Dtag *unit);
72 void Dtag_next(Dtag *unit, int inNumSamples);
73
74 }
75
76 /////////////////////////////////////////////////////////////
77
78
79 #define CHECK_BUF \
80 if (!bufData) { \
81 unit->mDone = true; \
82 ClearUnitOutputs(unit, inNumSamples); \
83 return; \
84 }
85
86
87 /////////////////////////////////////////////////////////////
88
89 enum {
90 dtag_tape_param,
91 dtag_deletion_number,
92 dtag_recycle,
93 dtag_mode,
94 dtag_axiom_size,
95 dtag_num_rules,
96 dtag_argoffset
97 };
98
99
100
DbufTag_initInputs(DbufTag * unit,int argOffset,int size)101 void DbufTag_initInputs(DbufTag *unit, int argOffset, int size)
102 {
103 int memsize = size * sizeof(int);
104
105 unit->m_rule_lengths = (int*)RTAlloc(unit->mWorld, memsize);
106 memset(unit->m_rule_lengths, 0, memsize);
107
108 unit->m_rule_offsets = (int*)RTAlloc(unit->mWorld, memsize);
109 memset(unit->m_rule_offsets, 0, memsize);
110
111
112 for(int i=0; i < size; i++) {
113 unit->m_rule_lengths[i] = (int) IN0(i + argOffset); // drop first n args
114 }
115
116 // calculate positions
117 int position = argOffset + size;
118 for(int i=0; i < size; i++) {
119 unit->m_rule_offsets[i] = position;
120 position += unit->m_rule_lengths[i];
121 // printf("m_rule_offsets[%d]: %d\n", i, unit->m_rule_offsets[i]);
122 }
123 }
124
125
DbufTag_reset(DbufTag * unit,int recycle,int inNumSamples)126 void DbufTag_reset(DbufTag *unit, int recycle, int inNumSamples)
127 {
128 GET_BUF
129 CHECK_BUF
130 RESETINPUT(dtag_deletion_number); // reset deletion number
131
132 // if axiom size exceeds buffer, omit part of the axiom.
133 if(unit->m_axiom_size > (int) bufFrames) {
134 unit->m_axiom_size = (int) bufFrames;
135 }
136
137 if(recycle == 0) {
138 // recycle = 0 - write axiom to buffer again.
139 unit->m_read_pos = 0;
140 unit->m_write_pos = (int32) unit->m_axiom_size;
141
142 if(unit->m_write_pos >= bufFrames) {
143 unit->m_write_pos = unit->m_write_pos % bufFrames;
144 }
145 // write axiom to tape
146 for(int i = 0; i < unit->m_write_pos; i++) {
147 bufData[i] = (float) DEMANDINPUT_A(dtag_argoffset + i, inNumSamples);
148 // printf("axiom[%d] = %d\n", i, (int) bufData[i]);
149 }
150 } else if (recycle < 0) {
151 // recycle < 0 - write_pos is left where it is, read_pos is offset by recycle value
152 unit->m_read_pos = unit->m_write_pos + recycle;
153 if(unit->m_read_pos < 0) {
154 unit->m_read_pos = unit->m_read_pos % bufFrames;
155 }
156
157 } else {
158 // recycle > 0 - read_pos is left where it is, write_pos is offset by recycle value
159 unit->m_write_pos = unit->m_read_pos + recycle;
160 if(unit->m_write_pos >= bufFrames) {
161 unit->m_write_pos = unit->m_write_pos % bufFrames;
162 }
163 //printf("new write: %d, read: %d\n", unit->m_write_pos, unit->m_read_pos);
164 }
165 }
166
167
DbufTag_end(DbufTag * unit,int which_case,int inNumSamples)168 void DbufTag_end(DbufTag *unit, int which_case, int inNumSamples) {
169
170 int recycle = (int) DEMANDINPUT_A(dtag_recycle, inNumSamples);
171 int mode = (int) IN0(dtag_mode);
172
173 if(which_case == 0) {
174 DbufTag_reset(unit, recycle, inNumSamples);
175 if(mode == 4) {
176 printf("tag system was reset externally.\n");
177 if(recycle) { printf("recycling. axiom length: %d\n", recycle); }
178 }
179 return;
180 }
181
182 if((mode == 0) || (mode == which_case)) {
183 if(recycle) {
184 DbufTag_reset(unit, recycle, inNumSamples);
185 } else {
186 OUT0(0) = NAN;
187 }
188 return;
189 }
190 if(mode >= 4) {
191 printf("tag system halt: ");
192 if(which_case == 1) {
193 printf("divergence too large (buffer filled up).\n");
194 } else {
195 printf("terminated (string empty)\n");
196 }
197
198 if(recycle) {
199
200 printf("recycling. axiom length: %d\n", recycle);
201 //printf("new axiom:\n"); // todo.
202 DbufTag_reset(unit, recycle, inNumSamples);
203
204 GET_BUF
205 printf("new axiom (index %d..%d): ", unit->m_read_pos, unit->m_write_pos);
206 int32 n = unit->m_write_pos - unit->m_read_pos;
207 if(n < 0) { n = sc_wrap(n, 0, bufFrames - 1); }
208 for(int32 i=0; i < n; i++) {
209 int32 j = sc_wrap(unit->m_read_pos + i, 0, bufFrames - 1);
210 printf("%d ", (int)bufData[j]);
211 }
212 printf("\n");
213
214 } else {
215 OUT0(0) = NAN;
216 }
217 return;
218 }
219 OUT0(0) = NAN;
220 }
221
222
DbufTag_Ctor(DbufTag * unit)223 void DbufTag_Ctor(DbufTag *unit)
224 {
225 SETCALC(DbufTag_next);
226 unit->m_fbufnum = -1e9f;
227 unit->m_axiom_size = (int) IN0(dtag_axiom_size);
228 unit->m_numRules = (int) IN0(dtag_num_rules);
229
230 DbufTag_initInputs(unit, dtag_argoffset + unit->m_axiom_size, unit->m_numRules);
231 DbufTag_reset(unit, 0, 1);
232
233 OUT0(0) = 0.f;
234 }
235
236
DbufTag_Dtor(DbufTag * unit)237 void DbufTag_Dtor(DbufTag *unit)
238 {
239 RTFree(unit->mWorld, unit->m_rule_lengths);
240 RTFree(unit->mWorld, unit->m_rule_offsets);
241 }
242
243
DbufTag_next(DbufTag * unit,int inNumSamples)244 void DbufTag_next(DbufTag *unit, int inNumSamples)
245 {
246
247 GET_BUF
248 CHECK_BUF
249
250
251 int rule_length;
252 int cur_rule_pos, next_rule_pos;
253 int32 write_pos = unit->m_write_pos;
254 int32 read_pos = unit->m_read_pos;
255
256 float value = bufData[read_pos];
257 int ruleIndex = (int) value;
258
259 // verbose print mode
260 if(!(IN0(dtag_mode) < 5.f)) {
261 int max = bufFrames;
262 if(max > 32) { max = 32; }
263 for(int i=0; i<max; i++) {
264 if(i == write_pos) { printf(">"); } else if (i == read_pos) { printf("|"); } else { printf(" "); }
265 printf("%d", (int) bufData[i]);
266
267 }
268 printf("\n");
269 printf("apply rule %d\n", ruleIndex);
270
271 }
272
273 //printf("writepos: %d readpos: %d rule_length: %d\n", unit->m_write_pos, unit->m_read_pos, rule_length);
274
275 if (!inNumSamples) {
276 DbufTag_end(unit, 0, inNumSamples);
277 return;
278 }
279
280 int v = (int) DEMANDINPUT_A(dtag_deletion_number, inNumSamples);
281
282 if(ruleIndex >= unit-> m_numRules || (ruleIndex < 0)) {
283 // printf("no rule found for value %d\n", ruleIndex);
284 OUT0(0) = NAN; // no rule found
285 return;
286 } else {
287
288 OUT0(0) = value;
289
290 cur_rule_pos = unit->m_rule_offsets[ruleIndex];
291 rule_length = unit->m_rule_lengths[ruleIndex];
292
293 for(int i=0; i < rule_length; i++) {
294 // copy production rule.
295 bufData[write_pos] = DEMANDINPUT_A(cur_rule_pos + i, inNumSamples);
296 write_pos += 1;
297 if(write_pos == read_pos) {
298 DbufTag_end(unit, 1, inNumSamples);
299 return;
300 }
301 if(write_pos == bufFrames) {
302 write_pos = 0;
303 }
304 }
305
306 for(int j=0; j < v; j++) {
307 read_pos += 1;
308 if(write_pos == read_pos) {
309 DbufTag_end(unit, 2, inNumSamples);
310 return;
311 }
312 if(read_pos == bufFrames) {
313 read_pos = 0;
314 }
315 }
316 unit->m_write_pos = write_pos;
317 unit->m_read_pos = read_pos;
318 }
319
320 }
321
322
323 ///////////////////////////////////////////////////////
324
325
Dtag_initInputs(Dtag * unit,int argOffset,int size)326 void Dtag_initInputs(Dtag *unit, int argOffset, int size)
327 {
328
329 unit->m_tape_size = (int32) IN0(dtag_tape_param);
330
331 // make sure axiom isn't longer than the tape.
332 if(unit->m_axiom_size > (int) unit->m_tape_size) {
333 unit->m_axiom_size = (int) unit->m_tape_size;
334 }
335
336 // allocate tape
337 int32 memtapesize = (int32) unit->m_tape_size * sizeof(int);
338 unit->m_tape = (float*)RTAlloc(unit->mWorld, memtapesize);
339 memset(unit->m_tape, 0, memtapesize);
340
341
342 // allocate offsets and lengths
343 int memsize = size * sizeof(int);
344
345 unit->m_rule_lengths = (int*)RTAlloc(unit->mWorld, memsize);
346 memset(unit->m_rule_lengths, 0, memsize);
347
348 unit->m_rule_offsets = (int*)RTAlloc(unit->mWorld, memsize);
349 memset(unit->m_rule_offsets, 0, memsize);
350
351
352 for(int i=0; i < size; i++) {
353 unit->m_rule_lengths[i] = (int) IN0(i + argOffset); // drop first n args
354 }
355
356 // calculate positions
357 int position = argOffset + size;
358 for(int i=0; i < size; i++) {
359 unit->m_rule_offsets[i] = position;
360 position += unit->m_rule_lengths[i];
361 // printf("m_rule_offsets[%d]: %d\n", i, unit->m_rule_offsets[i]);
362 }
363 }
364
365
Dtag_reset(Dtag * unit,int recycle,int inNumSamples)366 void Dtag_reset(Dtag *unit, int recycle, int inNumSamples)
367 {
368
369 RESETINPUT(dtag_deletion_number); // reset deletion number
370 // other than in DbufTag, m_axiom_size doesn't have to be checked again here, since buffer is fix.
371 if(recycle == 0) {
372 // recycle = 0 - write axiom to buffer again.
373 unit->m_read_pos = 0;
374 unit->m_write_pos = (int32) unit->m_axiom_size;
375
376 // write axiom to tape
377 for(int i = 0; i < unit->m_axiom_size; i++) {
378 unit->m_tape[i] = DEMANDINPUT_A(dtag_argoffset + i, inNumSamples);
379 // printf("axiom[%d] = %d\n", i, unit->m_tape[i]);
380 }
381 } else if (recycle < 0) {
382 // recycle < 0 - write_pos is left where it is, read_pos is offset by recycle value
383 if(unit->m_write_pos >= unit->m_tape_size) {
384 unit->m_write_pos = unit->m_write_pos % unit->m_tape_size;
385 }
386 unit->m_read_pos = unit->m_write_pos + recycle;
387 if(unit->m_read_pos < 0) {
388 unit->m_read_pos = sc_wrap(unit->m_read_pos, 0, unit->m_tape_size - 1);
389 }
390 } else {
391 // recycle > 0 - read_pos is left where it is, write_pos is offset by recycle value
392 if(unit->m_read_pos >= unit->m_tape_size) {
393 unit->m_read_pos = unit->m_read_pos % unit->m_tape_size;
394 }
395 unit->m_write_pos = unit->m_read_pos + recycle;
396 if(unit->m_write_pos >= unit->m_tape_size) {
397 unit->m_write_pos = unit->m_write_pos % unit->m_tape_size;
398 }
399
400 }
401 }
402
403
Dtag_end(Dtag * unit,int which_case,int inNumSamples)404 void Dtag_end(Dtag *unit, int which_case, int inNumSamples) {
405
406 int recycle = (int) DEMANDINPUT_A(dtag_recycle, inNumSamples);
407 int mode = (int) IN0(dtag_mode);
408
409 if(which_case == 0) {
410 Dtag_reset(unit, recycle, inNumSamples);
411 if(mode == 4) {
412 printf("tag system was reset.\n");
413 if(recycle) { printf("recycling. axiom length: %d\n", recycle); }
414 }
415 return;
416 }
417
418 if((mode == 0) || (mode == which_case)) {
419 if(recycle) {
420 Dtag_reset(unit, recycle, inNumSamples);
421 } else {
422 OUT0(0) = NAN;
423 }
424 return;
425 }
426 if(mode >= 4) {
427 printf("tag system halt: ");
428 if(which_case == 1) {
429 printf("divergence too large (buffer filled up).\n");
430 } else {
431 printf("terminated (string empty)\n");
432 }
433
434 if(recycle) {
435 printf("recycling. axiom length: %d\n", recycle);
436
437 Dtag_reset(unit, recycle, inNumSamples);
438
439 printf("new axiom (index %d..%d): ", unit->m_read_pos, unit->m_write_pos);
440 int32 n = unit->m_write_pos - unit->m_read_pos;
441 if(n < 0) { n = sc_wrap(n, 0, unit->m_tape_size - 1); }
442 for(int32 i=0; i < n; i++) {
443 int32 j = sc_wrap(unit->m_read_pos + i, 0, unit->m_tape_size - 1);
444 printf("%d ", (int)unit->m_tape[j]);
445 }
446 printf("\n");
447
448 } else {
449 OUT0(0) = NAN;
450 }
451 return;
452 }
453 OUT0(0) = NAN;
454 }
455
456
Dtag_Ctor(Dtag * unit)457 void Dtag_Ctor(Dtag *unit)
458 {
459
460 SETCALC(Dtag_next);
461
462 unit->m_axiom_size = (int) IN0(dtag_axiom_size);
463 unit->m_numRules = (int) IN0(dtag_num_rules);
464
465 // initialise and reset
466 Dtag_initInputs(unit, dtag_argoffset + unit->m_axiom_size, unit->m_numRules);
467 Dtag_reset(unit, 0, 1);
468
469 OUT0(0) = 0.f;
470 }
471
472
Dtag_Dtor(Dtag * unit)473 void Dtag_Dtor(Dtag *unit)
474 {
475 RTFree(unit->mWorld, unit->m_rule_lengths);
476 RTFree(unit->mWorld, unit->m_rule_offsets);
477 RTFree(unit->mWorld, unit->m_tape);
478 }
479
Dtag_next(Dtag * unit,int inNumSamples)480 void Dtag_next(Dtag *unit, int inNumSamples)
481 {
482
483 int rule_length;
484 int cur_rule_pos, next_rule_pos;
485
486 int32 write_pos = unit->m_write_pos;
487 int32 read_pos = unit->m_read_pos;
488 int32 tape_size = unit->m_tape_size;
489 float *tape = unit->m_tape;
490 float tapeVal = tape[read_pos];
491 int ruleIndex = (int) tapeVal;
492
493
494 // verbose print mode
495 if(!(IN0(dtag_mode) < 5.f)) {
496 int max = (int) unit->m_tape_size;
497 if(max > 32) { max = 32; }
498 for(int i=0; i<max; i++) {
499 if(i == write_pos) { printf(">"); } else if (i == read_pos) { printf("|"); } else { printf(" "); }
500 printf("%d", (int) unit->m_tape[i]);
501
502 }
503 printf("\n");
504 printf("apply rule %d\n", ruleIndex);
505 }
506
507
508
509 if (!inNumSamples) {
510 Dtag_end(unit, 0, 1);
511 return;
512 }
513
514 int v = (int) DEMANDINPUT_A(dtag_deletion_number, inNumSamples);
515
516 //printf("ruleIndex: %d rulesize: %d\n", ruleIndex, unit->m_numRules);
517 if(ruleIndex >= unit->m_numRules || (ruleIndex < 0)) {
518 // printf("no rule found for value %d rulesize: %d\n", ruleIndex, unit->m_numRules);
519 OUT0(0) = NAN; // no rule found
520 return;
521 } else {
522 OUT0(0) = tapeVal;
523 cur_rule_pos = unit->m_rule_offsets[ruleIndex];
524 rule_length = unit->m_rule_lengths[ruleIndex];
525
526 for(int i=0; i < rule_length; i++) {
527 tape[write_pos] = DEMANDINPUT_A(cur_rule_pos + i, inNumSamples);
528 write_pos += 1;
529 if(write_pos == read_pos) {
530 Dtag_end(unit, 1, inNumSamples);
531 return;
532 }
533 if(write_pos == tape_size) {
534 write_pos = 0;
535 }
536 }
537 for(int j=0; j < v; j++) {
538 read_pos += 1;
539 if(write_pos == read_pos) {
540 Dtag_end(unit, 2, inNumSamples);
541 return;
542 }
543 if(read_pos == tape_size) {
544 read_pos = 0;
545 }
546 }
547 unit->m_write_pos = write_pos;
548 unit->m_read_pos = read_pos;
549 }
550
551 }
552
553
554
555
556
557
558 struct Dfsm : public Unit
559 {
560 //int m_repeats;
561 int m_num_sizes;
562 int m_num_states;
563 int m_state_offset;
564 int *m_nextstate_indices;
565 int *m_nextstate_sizes;
566 int m_current_state;
567 int m_current_state_offset;
568 float m_count;
569 int m_end;
570 };
571
572
573 extern "C"
574 {
575 void Dfsm_Ctor(Dfsm *unit);
576 void Dfsm_Dtor(Dfsm *unit);
577 void Dfsm_next(Dfsm *unit, int inNumSamples);
578
579 };
580
581
582
583 //////////////////////////////////////////////////////////////////////////////////////////////////
584
Dfsm_reset(Dfsm * unit)585 void Dfsm_reset(Dfsm *unit) {
586 unit->m_current_state = 0;
587 unit->m_end = 0;
588 unit->m_count = 0.f;
589 for(int i = 0; i < unit->m_num_states; i++) {
590 // // printf("reset input[%d]\n", unit->m_state_offset + i);
591 RESETINPUT(unit->m_state_offset + i);
592 }
593 }
594
Dfsm_next(Dfsm * unit,int inNumSamples)595 void Dfsm_next(Dfsm *unit, int inNumSamples)
596 {
597 int current_state_offset, state_offset;
598 int choice;
599 int index_index;
600 int next_index;
601 float outval;
602
603 // // printf("\n\n\n ------- \n");
604
605 ////////////////////// reset /////////////////////////
606 // current_state is the internal state, including exit / enty pair.
607 // i.e. first rule is pair [exit, entrance]
608
609 if (!inNumSamples) {
610 Dfsm_reset(unit);
611 // printf("resetting\n");
612 }
613
614 // get some member state
615 state_offset = unit->m_state_offset;
616 current_state_offset = unit->m_current_state_offset;
617
618 ////////////////////// embedding mode /////////////////////////
619 if(unit->m_count > 0.f) {
620 outval = DEMANDINPUT_A(current_state_offset, inNumSamples); // this will have to switch behaviour, depending on slotRepeats
621 if(sc_isnan(outval)) {
622
623 if(unit->m_end) {
624 // exit state last value. end.
625 OUT0(0) = NAN;
626 unit->m_end = 0;
627 unit->m_count = 0.f;
628 // // printf("output: NAN to end stream\n");
629 return;
630 } else {
631
632 // other state last value
633 // // printf("(1) resetting input %d\n", current_state_offset);
634 RESETINPUT(current_state_offset);
635 };
636
637 } else {
638 // embed current value of current state
639 // // printf("outval: %f\n", outval);
640 OUT0(0) = outval;
641 unit->m_count --;
642 return;
643 }
644 }
645
646 ////////////////////// init count /////////////////////////
647
648 // get new count
649 unit->m_count = DEMANDINPUT_A(0, inNumSamples) - 1.f; // offset: first value is embedded below.
650
651 if(sc_isnan(unit->m_count)) { // terminate and reset
652 RESETINPUT(0);
653 OUT0(0) = NAN;
654 unit->m_end = 0;
655 unit->m_count = 0.f;
656 // // printf("output: NAN to end stream\n");
657 return;
658 };
659
660
661
662 ////////////////////// finding next state /////////////////////////
663
664
665
666 if(unit->m_current_state >= unit->m_num_states) {
667 unit->m_current_state_offset = state_offset;
668 outval = DEMANDINPUT_A(unit->m_current_state_offset, inNumSamples); // get first state, which is the packed termination state
669 OUT0(0) = outval;
670 // // printf("going to exit state (1): %d end\n", unit->m_current_state);
671 // // printf("output: %f\n", outval);
672 unit->m_end = 1;
673 return;
674 }
675
676 // how many nextstates ?
677 float size = (float) unit->m_nextstate_sizes[unit->m_current_state];
678
679 // get random value and generate random offset (0..size)
680 float rand = DEMANDINPUT_A(1, inNumSamples);
681 choice = (int) sc_max(0.f, rand * size - 0.5f);
682
683 // look up the nextstate index
684 index_index = unit->m_nextstate_indices[unit->m_current_state] + choice; // we'll need to limit this /0..1/
685
686 // get the next state index from the input, add one for offset: first rule is pair [exit, entrance]
687 next_index = IN0(index_index) + 1;
688 unit->m_current_state= next_index;
689
690 current_state_offset = state_offset + next_index;
691
692 // exit
693 if(next_index >= unit->m_num_states) {
694 current_state_offset = state_offset; // get first state, which is the packed termination state
695 // // printf("going to exit state (2): %d end\n", next_index);
696 unit->m_end = 1;
697 }
698
699
700 // get first value
701 outval = DEMANDINPUT_A(current_state_offset, inNumSamples);
702 if(sc_isnan(outval)) {
703 // // printf("(1) resetting input %d\n", current_state_offset);
704 if(unit->m_end) {
705 outval = NAN;
706 } else {
707 RESETINPUT(current_state_offset);
708 outval = DEMANDINPUT_A(current_state_offset, inNumSamples);
709 }
710 }
711 OUT0(0) = outval;
712
713 // set member state
714 unit->m_current_state_offset = current_state_offset;
715
716 // printf("indexindex: %d choice: %d, previndex: %d nextindex: %d outval index: %d\n", index_index, choice, unit->m_current_state, next_index, state_offset + next_index);
717 // // printf("outval: %f\n", outval);
718 }
719
720
721
Dfsm_Ctor(Dfsm * unit)722 void Dfsm_Ctor(Dfsm *unit)
723 {
724 SETCALC(Dfsm_next);
725
726 int numStates = (int)IN0(2);
727 unit->m_num_states = numStates;
728
729 // keep state size information
730 int memNumSize = numStates * sizeof(int);
731 unit->m_nextstate_sizes = (int*)RTAlloc(unit->mWorld, memNumSize);
732 memset(unit->m_nextstate_sizes, 0, memNumSize);
733
734 for(int i = 0; i < numStates; i++) {
735 unit->m_nextstate_sizes[i] = (int) IN0(3 + i);
736 }
737
738
739 // keep state index information
740 unit->m_state_offset = 3 + numStates;
741 int nextOffset = unit->m_state_offset + numStates;
742
743 int memNumIndices = numStates * sizeof(int);
744 unit->m_nextstate_indices = (int*)RTAlloc(unit->mWorld, memNumIndices);
745 memset(unit->m_nextstate_indices, 0, memNumIndices);
746
747 for(int i = 0; i < numStates; i++) {
748 unit->m_nextstate_indices[i] = nextOffset;
749 nextOffset = nextOffset + unit->m_nextstate_sizes[i];
750 }
751
752 // reset
753 unit->m_current_state = 0;
754 unit->m_end = 0;
755 unit->m_count = 0.f;
756 OUT0(0) = 0.f;
757 }
758
759
Dfsm_Dtor(Dfsm * unit)760 void Dfsm_Dtor(Dfsm *unit)
761 {
762 RTFree(unit->mWorld, unit->m_nextstate_indices);
763 RTFree(unit->mWorld, unit->m_nextstate_sizes);
764 }
765
766
767 //////////////////////////////////////////////////////
768
769
770
PluginLoad(TagSystem)771 PluginLoad(TagSystem)
772 {
773 ft = inTable;
774 DefineDtorUnit(DbufTag);
775 DefineDtorUnit(Dtag);
776 DefineDtorUnit(Dfsm);
777
778 }
779