1
2 /*
3 cellular.c:
4
5 Copyright (C) 2011 Gleb Rogozinsky
6
7 This file is part of Csound.
8
9 The Csound Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 Csound is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with Csound; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 02110-1301 USA
23 */
24
25 #include "csdl.h"
26
27 // classical 1-D Cellular Automaton by Gleb Rogozinsky.
28 // It is the modified version of vcella opcode by Gabriel Maldonado
29
30 typedef struct {
31 OPDS h;
32 MYFLT *ktrig, *kreinit, *ioutFunc, *initStateFunc,
33 *iRuleFunc, *ielements;
34 MYFLT *currLine, *outVec, *initVec, *ruleVec;
35 int32_t elements, NewOld;
36 AUXCH auxch;
37 } CELL;
38
cell_set(CSOUND * csound,CELL * p)39 static int32_t cell_set(CSOUND *csound,CELL *p)
40 {
41 FUNC *ftp;
42 int32_t elements=0;
43 MYFLT *currLine, *initVec = NULL;
44
45 if (LIKELY((ftp = csound->FTnp2Finde(csound,p->ioutFunc)) != NULL)) {
46 p->outVec = ftp->ftable;
47 elements = (p->elements = (int32_t) *p->ielements);
48
49 if (UNLIKELY( elements > (int32_t)ftp->flen ))
50 return csound->InitError(csound, "%s",
51 Str("cell: invalid num of elements"));
52 }
53 else return csound->InitError(csound, "%s", Str("cell: invalid output table"));
54 if (LIKELY((ftp = csound->FTnp2Finde(csound,p->initStateFunc)) != NULL)) {
55 initVec = (p->initVec = ftp->ftable);
56 if (UNLIKELY(elements > (int32_t)ftp->flen ))
57 return csound->InitError(csound, "%s",
58 Str("cell: invalid num of elements"));
59 }
60 else
61 return csound->InitError(csound, "%s",
62 Str("cell: invalid initial state table"));
63 if (LIKELY((ftp = csound->FTnp2Finde(csound,p->iRuleFunc)) != NULL)) {
64 p->ruleVec = ftp->ftable;
65 }
66 else
67 return csound->InitError(csound, "%s", Str("cell: invalid rule table"));
68
69 if (p->auxch.auxp == NULL)
70 csound->AuxAlloc(csound, elements * sizeof(MYFLT) * 2, &p->auxch);
71 currLine = (p->currLine = (MYFLT *) p->auxch.auxp);
72 p->NewOld = 0;
73 memcpy(currLine, initVec, sizeof(MYFLT)*elements);
74 /* do { */
75 /* *currLine++ = *initVec++; */
76 /* } while (--elements); */
77
78
79 return OK;
80 }
81
cell(CSOUND * csound,CELL * p)82 static int32_t cell(CSOUND *csound,CELL *p)
83 {
84 IGN(csound);
85 if (*p->kreinit) {
86 p->NewOld = 0;
87 memcpy(p->currLine, p->initVec, sizeof(MYFLT)*p->elements);
88 /* do { */
89 /* *currLine++ = *initVec++; */
90 /* } while (--elements); */
91 }
92 if (*p->ktrig) {
93 int32_t j, elements = p->elements, jm1;
94 MYFLT *actual, *previous, *outVec = p->outVec , *ruleVec = p->ruleVec;
95
96 previous = &(p->currLine[elements * p->NewOld]);
97 p->NewOld += 1;
98 p->NewOld %= 2;
99 actual = &(p->currLine[elements * p->NewOld]);
100 // Cellular Engine
101
102 for (j=0; j < elements; j++) {
103
104 jm1 = (j < 1) ? elements-1 : j-1;
105 outVec[j] = previous[j];
106 actual[j] = ruleVec[(int32_t)(previous[jm1]*4 + previous[j]*2 +
107 previous[(j+1) % elements])];
108 }
109
110 } else {
111 int32_t
112 elements = p->elements;
113 MYFLT *actual = &(p->currLine[elements * !(p->NewOld)]);
114 memcpy(p->outVec, actual, sizeof(MYFLT)*elements);
115 /* do { */
116 /* *outVec++ = *actual++ ; */
117 /* } while (--elements); */
118 }
119 return OK;
120 }
121
122
123 #define S sizeof
124
125 static OENTRY localops[] = {
126 {"cell", S(CELL), TB, 3, "", "kkiiii",(SUBR)cell_set, (SUBR)cell }
127 };
128
129 LINKAGE
130
131 // Author: Gleb Rogozinsky, October 2011
132