/* cellular.c: Copyright (C) 2011 Gleb Rogozinsky This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "csdl.h" // classical 1-D Cellular Automaton by Gleb Rogozinsky. // It is the modified version of vcella opcode by Gabriel Maldonado typedef struct { OPDS h; MYFLT *ktrig, *kreinit, *ioutFunc, *initStateFunc, *iRuleFunc, *ielements; MYFLT *currLine, *outVec, *initVec, *ruleVec; int32_t elements, NewOld; AUXCH auxch; } CELL; static int32_t cell_set(CSOUND *csound,CELL *p) { FUNC *ftp; int32_t elements=0; MYFLT *currLine, *initVec = NULL; if (LIKELY((ftp = csound->FTnp2Finde(csound,p->ioutFunc)) != NULL)) { p->outVec = ftp->ftable; elements = (p->elements = (int32_t) *p->ielements); if (UNLIKELY( elements > (int32_t)ftp->flen )) return csound->InitError(csound, "%s", Str("cell: invalid num of elements")); } else return csound->InitError(csound, "%s", Str("cell: invalid output table")); if (LIKELY((ftp = csound->FTnp2Finde(csound,p->initStateFunc)) != NULL)) { initVec = (p->initVec = ftp->ftable); if (UNLIKELY(elements > (int32_t)ftp->flen )) return csound->InitError(csound, "%s", Str("cell: invalid num of elements")); } else return csound->InitError(csound, "%s", Str("cell: invalid initial state table")); if (LIKELY((ftp = csound->FTnp2Finde(csound,p->iRuleFunc)) != NULL)) { p->ruleVec = ftp->ftable; } else return csound->InitError(csound, "%s", Str("cell: invalid rule table")); if (p->auxch.auxp == NULL) csound->AuxAlloc(csound, elements * sizeof(MYFLT) * 2, &p->auxch); currLine = (p->currLine = (MYFLT *) p->auxch.auxp); p->NewOld = 0; memcpy(currLine, initVec, sizeof(MYFLT)*elements); /* do { */ /* *currLine++ = *initVec++; */ /* } while (--elements); */ return OK; } static int32_t cell(CSOUND *csound,CELL *p) { IGN(csound); if (*p->kreinit) { p->NewOld = 0; memcpy(p->currLine, p->initVec, sizeof(MYFLT)*p->elements); /* do { */ /* *currLine++ = *initVec++; */ /* } while (--elements); */ } if (*p->ktrig) { int32_t j, elements = p->elements, jm1; MYFLT *actual, *previous, *outVec = p->outVec , *ruleVec = p->ruleVec; previous = &(p->currLine[elements * p->NewOld]); p->NewOld += 1; p->NewOld %= 2; actual = &(p->currLine[elements * p->NewOld]); // Cellular Engine for (j=0; j < elements; j++) { jm1 = (j < 1) ? elements-1 : j-1; outVec[j] = previous[j]; actual[j] = ruleVec[(int32_t)(previous[jm1]*4 + previous[j]*2 + previous[(j+1) % elements])]; } } else { int32_t elements = p->elements; MYFLT *actual = &(p->currLine[elements * !(p->NewOld)]); memcpy(p->outVec, actual, sizeof(MYFLT)*elements); /* do { */ /* *outVec++ = *actual++ ; */ /* } while (--elements); */ } return OK; } #define S sizeof static OENTRY localops[] = { {"cell", S(CELL), TB, 3, "", "kkiiii",(SUBR)cell_set, (SUBR)cell } }; LINKAGE // Author: Gleb Rogozinsky, October 2011