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