[PD-cvs] externals/pdp/scaf/pdp Makefile, 1.3, 1.4 pdp_ca.c, 1.4, 1.5 pdp_ca_system.c, 1.3, 1.4 scaf_feeder.s, 1.2, 1.3
Hans-Christoph Steiner
eighthave at users.sourceforge.net
Fri Dec 16 02:05:39 CET 2005
- Previous message: [PD-cvs] externals/pdp/puredata CONTENTS, 1.2, 1.3 Makefile, 1.2, 1.3 pdp_base.c, 1.2, 1.3 pdp_comm.c, 1.2, 1.3 pdp_compat.c, 1.2, 1.3 pdp_control.c, 1.2, 1.3 pdp_dpd_base.c, 1.2, 1.3 pdp_imagebase.c, 1.2, 1.3 pdp_queue.c, 1.2, 1.3 pdp_ut.c, 1.2, 1.3
- Next message: [PD-cvs] externals/pdp/scaf COPYING, 1.4, 1.5 Makefile, 1.5, 1.6 Makefile.config, 1.5, 1.6 Makefile.config.in, 1.4, 1.5 README, 1.5, 1.6 README.scaf, 1.4, 1.5 TODO, 1.4, 1.5 configure, 1.2, 1.3 configure.ac, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/pure-data/externals/pdp/scaf/pdp
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/scaf/pdp
Added Files:
Makefile pdp_ca.c pdp_ca_system.c scaf_feeder.s
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: pdp_ca.c ---
/*
* Pure Data Packet module for cellular automata
* Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp_ca.h"
#include "pdp_internals.h"
#include <dlfcn.h>
#include <stdio.h>
t_class *pdp_ca_class; // a cellular automaton processor: single input - single output
//t_class *pdp_ca2_class; // double input - single output
t_class *pdp_ca2image_class; // converter from ca -> grey/yv12
t_class *pdp_image2ca_class; // converter from grey/yv12 -> ca
// *********************** CA CLASS STUFF *********************
// this is defined in the makefile
// #define PDP_CA_RULES_LIB "/path/default.scafo"
#define PDP_CA_STACKSIZE 256
#define PDP_CA_MODE_1D 1
#define PDP_CA_MODE_2D 2
typedef struct pdp_ca_data_struct
{
unsigned int env[2*4];
unsigned int reg[2*4];
unsigned int stack[2*PDP_CA_STACKSIZE];
short int random_seed[4];
} t_pdp_ca_data;
typedef struct pdp_ca_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
int x_queue_id;
/* double buffering data packets */
int x_packet0;
int x_packet1;
/* some data on the ca_routine */
void (*x_ca_routine)(void);
void *x_ca_libhandle;
char *x_ca_rulenames;
int x_ca_nbrules;
char ** x_ca_rulename;
t_symbol *x_lastrule;
/* nb of iterations */
int x_iterations;
/* shift ca on output */
int x_horshift;
int x_vershift;
/* operation mode */
int x_mode;
int x_fullscreen1d;
/* aligned vector data */
t_pdp_ca_data *x_data;
/* output packet type */
t_symbol *x_packet_type;
} t_pdp_ca;
/* 1D: process from packet0 -> packet0 */
static void pdp_ca_process_ca_1D(t_pdp_ca *x)
{
t_pdp *header = pdp_packet_header(x->x_packet0);
unsigned int *data = (unsigned int *)pdp_packet_data (x->x_packet0);
int width = pdp_type_ca_info(header)->width;
int height = pdp_type_ca_info(header)->height;
int i;
unsigned int saved;
/* load TOS in middle of buffer to limit the effect of stack errors */
unsigned int *tos = &x->x_data->stack[2*(PDP_CA_STACKSIZE/2)];
unsigned int *env = &x->x_data->env[0];
unsigned int *reg = &x->x_data->reg[0];
void *ca_routine = x->x_ca_routine;
unsigned int rtos;
/* double word width: number of unsigned ints per row */
int dwwidth = width >> 5;
int currow = pdp_type_ca_info(header)->currow;
unsigned long long result = 0;
unsigned short temp;
unsigned short *usdata;
/* set destination row to 4th row from top (ca time horizon is 3 deep) */
int dwrow0 = (((currow + height - 3) % height) * width) >> 5;
int dwrow1 = (((currow + height - 2) % height) * width) >> 5;
int dwrow2 = (((currow + height - 1) % height) * width) >> 5;
int dwrow3 = (currow * width) >> 5;
/* exit if there isn't a valid routine */
if(!ca_routine) return;
/* compute new row */
for(i=0; i < (dwwidth-1) ; i+=1){
env[0] = data[dwrow0 + i];
env[1] = data[dwrow0 + i + 1];
env[2] = data[dwrow1 + i];
env[3] = data[dwrow1 + i + 1];
env[4] = data[dwrow2 + i];
env[5] = data[dwrow2 + i + 1];
result = scaf_feeder(tos, reg, ca_routine, env);
data[dwrow3 + i] = result & 0xffffffff;
}
// i == dwwidth-1
/* compute last column in row */
env[0] = data[dwrow0 + i];
env[1] = data[dwrow0];
env[2] = data[dwrow1 + i];
env[3] = data[dwrow1];
env[4] = data[dwrow2 + i];
env[5] = data[dwrow2];
result = scaf_feeder(tos, reg, ca_routine, env);
data[dwrow3 + i] = result & 0xffffffff;
/* undo the shift */
usdata = (unsigned short *)(&data[dwrow3]);
temp = usdata[(dwwidth*2)-1];
for (i = (dwwidth*2 - 1); i > 0; i--){
usdata[i] = usdata[i-1];
}
usdata[0] = temp;
/* check data stack pointer */
rtos = (unsigned int)tos;
if (env[0] != rtos){
if (env[0] > rtos) post("pdp_ca: ERROR: stack underflow detected in ca routine");
if (env[0] < rtos) post("pdp_ca: ERROR: ca routine returned more than one item");
x->x_ca_routine = 0;
post("pdp_ca: rule disabled");
}
/* save current row */
pdp_type_ca_info(header)->currow = (currow + 1) % height;
}
/* 2D: process from packet0 -> packet1 */
static void pdp_ca_process_ca_2D(t_pdp_ca *x)
{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
t_pdp *header1 = pdp_packet_header(x->x_packet1);
unsigned int *data0 = (unsigned int *)pdp_packet_data (x->x_packet0);
unsigned int *data1 = (unsigned int *)pdp_packet_data (x->x_packet1);
int width = pdp_type_ca_info(header0)->width;
int height = pdp_type_ca_info(header0)->height;
int i,j;
/* load TOS in middle of buffer to limit the effect of stack errors */
unsigned int *tos = &x->x_data->stack[2*(PDP_CA_STACKSIZE/2)];
unsigned int *env = &x->x_data->env[0];
unsigned int *reg = &x->x_data->reg[0];
void *ca_routine = x->x_ca_routine;
unsigned int rtos;
int offset = pdp_type_ca_info(header0)->offset;
int xoffset = offset % width;
int yoffset = offset / width;
/* double word width: number of unsigned ints per row */
int dwwidth = width >> 5;
unsigned long long result = 0;
/* exit if there isn't a valid routine */
if(!ca_routine) return;
if(!header0) return;
if(!header1) return;
//post("pdp_ca: PRE offset: %d, xoffset: %d, yoffset: %d", offset, xoffset, yoffset);
/* calculate new offset: lines shift up, rows shift left by 16 cells */
xoffset = (xoffset + width - 16) % width;
yoffset = (yoffset + height - 1) % height;
offset = yoffset * width + xoffset;
//post("pdp_ca: PST offset: %d, xoffset: %d, yoffset: %d", offset, xoffset, yoffset);
pdp_type_ca_info(header1)->offset = offset;
for(j=0; j<dwwidth*(height - 2); j+=(dwwidth<<1)){
for(i=0; i < (dwwidth-1) ; i+=1){
env[0] = data0[i + j];
env[1] = data0[i + j + 1];
env[2] = data0[i + j + dwwidth];
env[3] = data0[i + j + dwwidth + 1];
env[4] = data0[i + j + (dwwidth<<1)];
env[5] = data0[i + j + (dwwidth<<1) + 1];
env[6] = data0[i + j + (dwwidth<<1) + dwwidth];
env[7] = data0[i + j + (dwwidth<<1) + dwwidth + 1];
result = scaf_feeder(tos, reg, ca_routine, env);
data1[i + j] = result & 0xffffffff;
data1[i + j + dwwidth] = result >> 32;
}
// i == dwwidth-1
env[0] = data0[i + j];
env[1] = data0[j];
env[2] = data0[i + j + dwwidth];
env[3] = data0[j + dwwidth];
env[4] = data0[i + j + (dwwidth<<1)];
env[5] = data0[j + (dwwidth<<1)];
env[6] = data0[i + j + (dwwidth<<1) + dwwidth];
env[7] = data0[j + (dwwidth<<1) + dwwidth];
result = scaf_feeder(tos, reg, ca_routine, env);
data1[i + j] = result & 0xffffffff;
data1[i + j + dwwidth] = result >> 32;
}
// j == dwwidth*(height - 2)
for(i=0; i < (dwwidth-1) ; i+=1){
env[0] = data0[i + j];
env[1] = data0[i + j + 1];
env[2] = data0[i + j + dwwidth];
env[3] = data0[i + j + dwwidth + 1];
env[4] = data0[i];
env[5] = data0[i + 1];
env[6] = data0[i + dwwidth];
env[7] = data0[i + dwwidth + 1];
result = scaf_feeder(tos, reg, ca_routine, env);
data1[i + j] = result & 0xffffffff;
data1[i + j + dwwidth] = result >> 32;
}
// j == dwwidth*(height - 2)
// i == dwwidth-1
env[0] = data0[i + j];
env[1] = data0[j];
env[2] = data0[i + j + dwwidth];
env[3] = data0[j + dwwidth];
env[4] = data0[i];
env[5] = data0[0];
env[6] = data0[i + dwwidth];
env[7] = data0[dwwidth];
result = scaf_feeder(tos, reg, ca_routine, env);
data1[i + j] = result & 0xffffffff;
data1[i + j + dwwidth] = result >> 32;
/* check data stack pointer */
rtos = (unsigned int)tos;
if (env[0] != rtos){
if (env[0] > rtos) post("pdp_ca: ERROR: stack underflow detected in ca routine");
if (env[0] < rtos) post("pdp_ca: ERROR: ca routine returned more than one item");
x->x_ca_routine = 0;
post("pdp_ca: rule disabled");
}
return;
}
static void pdp_ca_swappackets(t_pdp_ca *x)
{
/* swap packets */
int packet = x->x_packet1;
x->x_packet1 = x->x_packet0;
x->x_packet0 = packet;
}
/* tick advance CA one timestep */
static void pdp_ca_bang_thread(t_pdp_ca *x)
{
int encoding;
int packet;
int i;
int iterations = x->x_iterations;
/* invariant: the two packets are allways valid and compatible
so a bang is allways possible. this means that in the pdp an
invalid packet needs to be converted to a valid one */
if (-1 == x->x_packet0) pdp_post("warning: packet 0 invalid");
if (-1 == x->x_packet1) pdp_post("warning: packet 1 invalid");
if (PDP_CA_MODE_2D == x->x_mode){
for(i=0; i < iterations; i++){
/* process form packet0 -> packet1 */
pdp_ca_process_ca_2D(x);
/* swap */
pdp_ca_swappackets(x);
}
}
else if (PDP_CA_MODE_1D == x->x_mode){
if (x->x_fullscreen1d){
t_pdp *header0 = pdp_packet_header(x->x_packet0);
pdp_type_ca_info(header0)->currow = 0;
pdp_type_ca_info(header0)->offset = 0;
iterations = pdp_type_ca_info(header0)->height;
}
for(i=0; i < iterations; i++){
pdp_ca_process_ca_1D(x);
}
}
}
static void pdp_ca_sendpacket(t_pdp_ca *x)
{
/* adjust offset before sending */
t_pdp *header0 = pdp_packet_header(x->x_packet0);
int offset, width, height, xoffset, yoffset, horshift, vershift;
if (!header0) return;
offset = pdp_type_ca_info(header0)->offset;
width = pdp_type_ca_info(header0)->width;
height = pdp_type_ca_info(header0)->height;
xoffset = offset % width;
yoffset = offset / width;
horshift = x->x_horshift;
vershift = x->x_vershift;
horshift %= width;
if (horshift < 0) horshift += width;
vershift %= height;
if (vershift < 0) vershift += height;
xoffset = (xoffset + horshift) % width;
yoffset = (yoffset + vershift) % height;
offset = yoffset * width + xoffset;
pdp_type_ca_info(header0)->offset = offset;
/* output the packet */
outlet_pdp(x->x_outlet0, x->x_packet0);
}
static void pdp_ca_bang(t_pdp_ca *x)
{
/* we don't use input packets for testing dropping here
but check the queue_id to see if processing is
still going on */
if (-1 == x->x_queue_id){
pdp_queue_add(x, pdp_ca_bang_thread, pdp_ca_sendpacket, &x->x_queue_id);
}
else{
pdp_control_notify_drop(-1);
}
}
/* this method stores the packet into x->x_packet0 (the packet
to be processed) if it is valid. x->x_packet1 is not compatible
it is regenerated so that it is
in short, when this routine returns both packets are valid
and compatible.
*/
static void pdp_ca_copy_rw_if_valid(t_pdp_ca *x, int packet)
{
t_pdp *header = pdp_packet_header(packet);
t_pdp *header1 = pdp_packet_header(x->x_packet1);
int grabpacket;
int convertedpacket;
/* check if header is valid */
if (!header) return;
if (PDP_CA != header->type) return;
if (PDP_CA_STANDARD != pdp_type_ca_info(header)->encoding) return;
/* packet is a ca, register it */
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_copy_rw(packet);
/* make sure we have the right header */
header = pdp_packet_header(x->x_packet0);
/* make sure that the other packet is compatible */
if ((pdp_type_ca_info(header1)->width != pdp_type_ca_info(header)->width) ||
(pdp_type_ca_info(header1)->height != pdp_type_ca_info(header)->height)) {
/* if not, throw away and clone the new one */
pdp_packet_mark_unused(x->x_packet1);
x->x_packet1 = pdp_packet_clone_rw(x->x_packet0);
}
if (-1 == x->x_packet0) pdp_post("warning: packet 0 invalid");
if (-1 == x->x_packet1) pdp_post("warning: packet 1 invalid");
};
/* hot packet inlet */
static void pdp_ca_input_0(t_pdp_ca *x, t_symbol *s, t_floatarg f)
{
if (s == gensym("register_rw")){
pdp_ca_copy_rw_if_valid(x, (int)f);
}
else if (s == gensym("process")){
pdp_ca_bang(x);
}
}
/* cold packet inlet */
static void pdp_ca_input_1(t_pdp_ca *x, t_symbol *s, t_floatarg f)
{
if (s == gensym("register_rw"))
{
pdp_ca_copy_rw_if_valid(x, (int)f);
}
}
static void pdp_ca_rule_string(t_pdp_ca *x, char *c)
{
char tmp[256];
void (*ca_routine)(void);
/* check if we can find string */
sprintf(tmp, "rule_%s", c);
if (!(ca_routine = dlsym(x->x_ca_libhandle, tmp))){
post("pdp_ca: can't fine ca rule %s (symbol: %s)", c, tmp);
return;
}
/* ok, so store routine address */
else{
x->x_ca_routine = ca_routine;
x->x_lastrule = gensym(c);
}
}
static void pdp_ca_rule(t_pdp_ca *x, t_symbol *s)
{
/* make sure lib is loaded */
if (!x->x_ca_libhandle) return;
/* set rule by name */
pdp_ca_rule_string(x, s->s_name);
}
static void pdp_ca_rule_index(t_pdp_ca *x, t_float f)
{
int i = (int)f;
/* make sure lib is loaded */
if (!x->x_ca_libhandle) return;
/* check index */
if (i<0) return;
if (i>=x->x_ca_nbrules) return;
/* set rule by index */
pdp_ca_rule_string(x, x->x_ca_rulename[i]);
}
static void pdp_ca_close(t_pdp_ca *x)
{
if (x->x_ca_libhandle){
dlclose(x->x_ca_libhandle);
x->x_ca_libhandle = 0;
x->x_ca_routine = 0;
if (x->x_ca_rulename){
free (x->x_ca_rulename);
x->x_ca_rulename = 0;
}
}
}
static void pdp_ca_printrules(t_pdp_ca *x)
{
int i;
if (!(x->x_ca_libhandle)) return;
post("pdp_ca: found %d rules: ", x->x_ca_nbrules);
for(i=0;i<x->x_ca_nbrules; i++) post("%3d: %s ", i, x->x_ca_rulename[i]);
}
/* open code library */
static void pdp_ca_openlib(t_pdp_ca *x, t_symbol *s)
{
char *c;
int words;
/* close current lib, if one */
pdp_ca_close(x);
/* try to open new lib */
if (!(x->x_ca_libhandle = dlopen(s->s_name, RTLD_NOW))){
post("pdp_ca: can't open ca library %s\n%s", s->s_name, dlerror());
x->x_ca_libhandle = 0;
return;
}
/* scan for valid rules */
if (!(x->x_ca_rulenames = (char *)dlsym(x->x_ca_libhandle, "rulenames"))){
post("pdp_ca: ERROR: %s does not contain a name table. closing.", s->s_name);
pdp_ca_close(x);
return;
}
/* count rules */
words = 0;
for(c = (char *)x->x_ca_rulenames; *c;){
words++;
while(*c++);
}
x->x_ca_nbrules = words;
x->x_ca_rulename = (char **)malloc(sizeof(char *) * words);
/* build name array */
words = 0;
for(c = (char *)x->x_ca_rulenames; *c;){
x->x_ca_rulename[words] = c;
words++;
while(*c++);
}
/* ok, we're done */
post("pdp_ca: opened rule library %s", s->s_name ,x->x_ca_nbrules);
/* print rule names */
//pdp_ca_printrules(x);
/* set last selected rule */
pdp_ca_rule(x, x->x_lastrule);
}
/* compile source file and open resulting code library */
static void pdp_ca_opensrc(t_pdp_ca *x, t_symbol *s)
{
#define TMPSIZE 1024
char commandline[TMPSIZE];
char library[TMPSIZE];
int status;
/* setup compiler args */
snprintf(library, TMPSIZE, "%so", s->s_name);
snprintf(commandline, TMPSIZE, "scafc %s %s", s->s_name, library);
/* call compiler */
if (system(commandline))
{
post ("pdp_ca: error compiling %s", s->s_name);
}
else
{
post("pdp_ca: compiled %s", s->s_name);
pdp_ca_openlib(x, gensym(library));
}
}
/* open a source file or a library, depending on extension */
static void pdp_ca_open(t_pdp_ca *x, t_symbol *s)
{
char *name = s->s_name;
char *end = name;
while(*end) end++;
if (end == name){
post("pdp_ca: invalid file name");
return;
}
/* if the name ends with 'o' assume it is a library */
if (end[-1] == 'o'){
pdp_ca_openlib(x, s);
}
/* otherwize, assume it is a source file */
else{
pdp_ca_opensrc(x, s);
}
}
/* init the current packet with random noise */
static void pdp_ca_rand(t_pdp_ca *x){
t_pdp *header = pdp_packet_header(x->x_packet0);
short int *data = (short int *) pdp_packet_data(x->x_packet0);
int i;
int nbshortints = (pdp_type_ca_info(header)->width >> 4) * pdp_type_ca_info(header)->height;
for(i=0; i<nbshortints; i++)
data[i] = random();
}
static void pdp_ca_newca(t_pdp_ca *x, t_float width, t_float height)
{
/* delete old packets */
pdp_packet_mark_unused(x->x_packet0);
pdp_packet_mark_unused(x->x_packet1);
/* create new packets */
x->x_packet0 = pdp_packet_new_ca(PDP_CA, width, height);
x->x_packet1 = pdp_packet_clone_rw(x->x_packet0);
}
static void pdp_ca_iterations(t_pdp_ca *x, t_float f)
{
int i = (int)f;
if (i < 0) i = 0;
x->x_iterations = i;
}
static void pdp_ca_horshift16(t_pdp_ca *x, t_float f)
{
x->x_horshift = 16 * (int)f;
}
static void pdp_ca_vershift(t_pdp_ca *x, t_float f)
{
x->x_vershift = (int)f;
}
static void pdp_ca_set1d(t_pdp_ca *x)
{
x->x_mode = PDP_CA_MODE_1D;
}
static void pdp_ca_set2d(t_pdp_ca *x)
{
x->x_mode = PDP_CA_MODE_2D;
}
static void pdp_ca_fullscreen1d(t_pdp_ca *x, t_floatarg f)
{
if (f == 0.0f) x->x_fullscreen1d = 0;
if (f == 1.0f) x->x_fullscreen1d = 1;
}
static void pdp_ca_free(t_pdp_ca *x)
{
pdp_packet_mark_unused(x->x_packet0);
pdp_packet_mark_unused(x->x_packet1);
pdp_ca_close(x);
free(x->x_data);
}
void *pdp_ca_new(void)
{
t_pdp_ca *x = (t_pdp_ca *)pd_new(pdp_ca_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("pdp"), gensym("pdp1"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("iterations"));
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1;
x->x_packet1 = -1;
x->x_queue_id = -1;
x->x_data = (t_pdp_ca_data *)malloc(sizeof(t_pdp_ca_data));
x->x_ca_routine = 0;
x->x_ca_libhandle = 0;
x->x_ca_rulename = 0;
x->x_horshift = 0;
x->x_vershift = 0;
pdp_ca_newca(x, 64, 64);
pdp_ca_iterations(x, 1);
pdp_ca_set2d(x);
pdp_ca_fullscreen1d(x, 0);
x->x_packet_type = gensym("grey");
x->x_lastrule = gensym("gameoflife");
pdp_ca_openlib(x, gensym(PDP_CA_RULES_LIB));
return (void *)x;
}
// *********************** CA CONVERTER CLASSES STUFF *********************
// TODO: move this to a separate file later together with other converters (part of system?)
#define PDP_CA2IMAGE 1
#define PDP_IMAGE2CA 2
typedef struct pdp_ca_conv_struct
{
t_object x_obj;
t_float x_f;
int x_threshold;
int x_packet;
t_outlet *x_outlet0;
/* solve identity crisis */
int x_whoami;
/* output packet type */
/* only greyscale for now */
t_symbol *x_packet_type;
} t_pdp_ca_conv;
/* hot packet inlet */
static void pdp_ca_conv_input_0(t_pdp_ca_conv *x, t_symbol *s, t_floatarg f)
{
int packet = -1;
if (s == gensym("register_ro")){
pdp_packet_mark_unused(x->x_packet);
x->x_packet = pdp_packet_copy_ro((int)f);
return;
}
else if (s == gensym("process")){
switch(x->x_whoami){
case PDP_CA2IMAGE:
packet = pdp_type_ca2grey(x->x_packet);
break;
case PDP_IMAGE2CA:
packet = pdp_type_grey2ca(x->x_packet, x->x_threshold);
break;
}
/* throw away the original packet */
pdp_packet_mark_unused(x->x_packet);
x->x_packet = -1;
/* pass the fresh packet */
pdp_packet_pass_if_valid(x->x_outlet0, &packet);
/* unregister the freshly created packet */
//pdp_packet_mark_unused(packet);
/* output if valid */
//if (-1 != packet) outlet_pdp(x->x_outlet0, packet);
}
}
void pdp_ca_conv_free(t_pdp_ca_conv *x)
{
pdp_packet_mark_unused(x->x_packet);
}
void pdp_image2ca_threshold(t_pdp_ca_conv *x, t_float f)
{
f *= 0x8000;
if (f < -0x7fff) f = -0x7fff;
if (f > 0x7fff) f = 0x7fff;
x->x_threshold = (short int)f;
}
void *pdp_ca2image_new(void)
{
t_pdp_ca_conv *x = (t_pdp_ca_conv *)pd_new(pdp_ca2image_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet_type = gensym("grey");
x->x_packet = -1;
x->x_whoami = PDP_CA2IMAGE;
return (void *)x;
}
void *pdp_image2ca_new(void)
{
t_pdp_ca_conv *x = (t_pdp_ca_conv *)pd_new(pdp_image2ca_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("threshold"));
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet_type = gensym("grey");
x->x_packet = -1;
x->x_whoami = PDP_IMAGE2CA;
x->x_threshold = 0x4000;
return (void *)x;
}
// *********************** CLASS SETUP FUNCTIONS *********************
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_ca2image_setup(void)
{
pdp_ca2image_class = class_new(gensym("pdp_ca2image"), (t_newmethod)pdp_ca2image_new,
(t_method)pdp_ca_conv_free, sizeof(t_pdp_ca), 0, A_NULL);
class_addmethod(pdp_ca2image_class, (t_method)pdp_ca_conv_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
void pdp_image2ca_setup(void)
{
pdp_image2ca_class = class_new(gensym("pdp_image2ca"), (t_newmethod)pdp_image2ca_new,
(t_method)pdp_ca_conv_free, sizeof(t_pdp_ca), 0, A_NULL);
class_addmethod(pdp_image2ca_class, (t_method)pdp_ca_conv_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_image2ca_class, (t_method)pdp_image2ca_threshold, gensym("threshold"), A_FLOAT, A_NULL);
}
void pdp_ca_setup(void)
{
pdp_ca_class = class_new(gensym("pdp_ca"), (t_newmethod)pdp_ca_new,
(t_method)pdp_ca_free, sizeof(t_pdp_ca), 0, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_iterations, gensym("iterations"), A_FLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_bang, gensym("bang"), A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_printrules, gensym("rules"), A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_rand, gensym("random"), A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_newca, gensym("ca"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_newca, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_horshift16, gensym("hshift16"), A_FLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_vershift, gensym("vshift"), A_FLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_close, gensym("close"), A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_openlib, gensym("openlib"), A_SYMBOL, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_opensrc, gensym("opensrc"), A_SYMBOL, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_open, gensym("open"), A_SYMBOL, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_rule, gensym("rule"), A_SYMBOL, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_rule_index, gensym("ruleindex"), A_FLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_input_1, gensym("pdp1"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_set1d, gensym("1D"), A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_set2d, gensym("2D"), A_NULL);
class_addmethod(pdp_ca_class, (t_method)pdp_ca_fullscreen1d, gensym("fullscreen1D"), A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_ca_system.c ---
/*
* Cellular Automata Extension Module for pdp - Main system code
* Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp_ca.h"
#include "pdp_internals.h"
/* all symbols are C-style */
#ifdef __cplusplus
extern "C"
{
#endif
/* check if packet is a valid ca packet */
int pdp_packet_ca_isvalid(int packet)
{
t_pdp *header = pdp_packet_header(packet);
if (!header) return 0;
if (PDP_CA != header->type) return 0;
if (PDP_CA_STANDARD != pdp_type_ca_info(header)->encoding) return 0;
return 1;
}
static t_pdp_symbol *pdp_packet_ca_get_description(int packet)
{
t_pdp *header = pdp_packet_header(packet);
char description[1024];
char *c = description;
int encoding;
if (!header) return pdp_gensym("invalid");
if (header->type == PDP_CA){
c += sprintf(c, "ca");
switch(pdp_type_ca_info(header)->encoding){
case PDP_CA_STANDARD: c += sprintf(c, "/1bit2D"); break;
default:
c += sprintf(c, "/unknown"); goto exit;
}
c += sprintf(c, "/%dx%d",
pdp_type_ca_info(header)->width,
pdp_type_ca_info(header)->height);
exit:
return pdp_gensym(description);
}
else return pdp_gensym("unknown");
}
/* create a new ca packet */
int pdp_packet_new_ca(int encoding, int width, int height)
{
int p;
int w = (int)width;
int h = (int)height;
int bytesize;
t_pdp *header;
/* ensure with = multiple of 64 */
w &= 0xffffffc0;
/* ensure height = multiple of 4 */
w &= 0xfffffffc;
w = (w<64) ? 64 : w;
h = (h<4) ? 4 : h;
bytesize = (w>>3) * h;
/* create new packets */
p = pdp_packet_new(PDP_CA, bytesize);
header = pdp_packet_header(p);
if (!header) {
pdp_post("error: can't create CA packet");
return -1;
}
pdp_type_ca_info(header)->encoding = PDP_CA_STANDARD;
pdp_type_ca_info(header)->width = w;
pdp_type_ca_info(header)->height = h;
pdp_type_ca_info(header)->offset = 0;
pdp_type_ca_info(header)->currow = 0; /* only used for 1D ca */
pdp_type_ca_info(header)->currow = 0;
header->desc = 0;
header->desc = pdp_packet_ca_get_description(p);
//post("creating %s", header->desc->s_name);
return p;
}
/* convert a CA packet to greyscale */
inline void _pdp_type_ca2grey_convert_word(unsigned short int source, short int *dest)
{
int i;
for (i = 15; i>=0; i--){
dest[i] = ((unsigned short)(((short int)(source & 0x8000)) >> 14)) >> 1;
source <<= 1;
}
}
int pdp_type_ca2grey(int packet)
{
int w, h, s, x, y, srcindex;
long long offset, xoffset, yoffset;
short int *dest;
unsigned short int *source;
t_pdp *header;
t_pdp *newheader;
int newpacket;
if (!(pdp_packet_ca_isvalid(packet))) return -1;
header = pdp_packet_header(packet);
w = pdp_type_ca_info(header)->width;
h = pdp_type_ca_info(header)->height;
s = w*h;
source = (unsigned short int *)pdp_packet_data(packet);
offset = pdp_type_ca_info(header)->offset;
yoffset = (offset / w) * w;
xoffset = offset % w;
//post("pdp_type_ca2grey: offset: %d, xoffset: %d, yoffset: %d", offset, xoffset, yoffset);
newpacket = pdp_packet_new_image_grey(w, h);
newheader = pdp_packet_header(newpacket);
if (!newheader) return -1;
//newheader->info.image.width = w;
//newheader->info.image.height = h;
//newheader->info.image.encoding = PDP_IMAGE_GREY;
dest = (short int *)pdp_packet_data(newpacket);
#define check_srcindex \
if (srcindex >= (s >> 4)) post ("pdp_type_ca2grey: srcindex out of bound");
#define check_dstindex \
if ((x+y) >= s) post ("pdp_type_ca2grey: dstindex out of bound");
/* debug : dont' shift offset
if (0){
for(y=0; y< (h*w); y+=w){
for(x=0; x<w; x+=16){
_pdp_type_ca2grey_convert_word (source[(x+y)>>4], &dest[x+y]);
}
}
return newpacket;
}
*/
/* create top left */
for (y=0; y < (h*w) - yoffset; y+=w) {
for (x=0; x< (w - xoffset); x+=16) {
srcindex = (x+xoffset + y+yoffset) >> 4;
//check_srcindex;
//check_dstindex;
_pdp_type_ca2grey_convert_word (source[srcindex], &dest[x+y]);
}
}
/* create top right */
for (y=0; y < (h*w) - yoffset; y+=w) {
for (x = (w - xoffset); x < w; x+=16) {
srcindex = (x+xoffset-w + y+yoffset) >> 4;
//check_srcindex;
//check_dstindex;
_pdp_type_ca2grey_convert_word (source[srcindex], &dest[x+y]);
}
}
/* create bottom left */
for (y=(h*w) - yoffset; y < h*w; y+=w) {
for (x=0; x< (w - xoffset); x+=16) {
srcindex = (x+xoffset + y+yoffset-(w*h)) >> 4;
//check_srcindex;
//check_dstindex;
_pdp_type_ca2grey_convert_word (source[srcindex], &dest[x+y]);
}
}
/* create bottom right */
for (y=(h*w) - yoffset; y < h*w; y+=w) {
for (x = (w - xoffset); x < w; x+=16) {
srcindex = (x+xoffset-w + y+yoffset-(w*h)) >> 4;
//check_srcindex;
//check_dstindex;
_pdp_type_ca2grey_convert_word (source[srcindex], &dest[x+y]);
}
}
return newpacket;
}
inline unsigned short int _pdp_type_grey2ca_convert_word(short int *src, short int threshold)
{
short int tmp;
short int dest = 0;
int i;
for (i = 15; i >= 0; i--){
dest <<= 1;
dest |= (src[i] > threshold);
}
return dest;
}
int pdp_type_grey2ca(int packet, short int threshold)
{
int w, h, s, x, y, srcindex;
long long offset, xoffset, yoffset;
short int *dest;
short int *source;
t_pdp *header;
t_pdp *newheader;
int newpacket;
if (!(pdp_packet_image_isvalid(packet))) return -1;
header = pdp_packet_header(packet);
w = header->info.image.width;
h = header->info.image.height;
s = w*h;
source = (unsigned short int *)pdp_packet_data(packet);
if ( (PDP_IMAGE_GREY != header->info.image.encoding)
&& (PDP_IMAGE_YV12 != header->info.image.encoding)) return -1;
newpacket = pdp_packet_new_ca(PDP_CA_STANDARD, w, h);
newheader = pdp_packet_header(newpacket);
if (!newheader) return -1;
dest = (short int *)pdp_packet_data(newpacket);
for(y=0; y< (h*w); y+=w){
for(x=0; x<w; x+=16){
dest[(x+y)>>4] = _pdp_type_grey2ca_convert_word (&source[x+y], threshold);
}
}
return newpacket;
}
/* returns a pointer to the ca subheader given the pdp header */
t_ca *pdp_type_ca_info(t_pdp *x){return (t_ca *)(&x->info.raw);}
void pdp_ca_setup(void);
void pdp_ca2image_setup(void);
void pdp_image2ca_setup(void);
static int _ca_to_image(int packet, t_pdp_symbol *template)
{
return pdp_type_ca2grey(packet);
}
static int _image_to_ca(int packet, t_pdp_symbol *template)
{
// convert with default threshold == 0.5
return pdp_type_grey2ca(packet, 0.5f);
}
void pdp_scaf_setup(void)
{
t_pdp_conversion_program *program;
/* babble */
post ("PDP: pdp_scaf extension library");
/* setup modules */
pdp_ca_setup();
pdp_ca2image_setup();
pdp_image2ca_setup();
/* setup type conversion */
program = pdp_conversion_program_new(_ca_to_image, 0);
pdp_type_register_conversion(pdp_gensym("ca/*/*"), pdp_gensym("image/*/*"), program);
pdp_type_register_conversion(pdp_gensym("ca/*/*"), pdp_gensym("image/grey/*"), program);
program = pdp_conversion_program_new(_image_to_ca, 0);
pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("ca/*/*"), program);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: Makefile ---
current: all_modules
include ../Makefile.config
OBJECTS = pdp_ca.o pdp_ca_system.o scaf_feeder.o
all_modules: $(OBJECTS)
clean:
rm -f *~
rm -f *.o
--- NEW FILE: scaf_feeder.s ---
# Pure Data Packet - scaf feeder routine.
# Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# for dup
.include "../compiler/scafmacro.s"
# *rg is only used for returning the stack pointer
# the 4 bit counter is using registers mm4-mm7 now
# long long scaf_feeder(void *tos, void *rg, *void() ca_rule, void *env)
.globl scaf_feeder
.type scaf_feeder, @function
scaf_feeder:
pushl %ebp
movl %esp, %ebp
push %esi
push %edi
movl 20(%ebp), %edi # load env ptr
movl 8(%ebp), %esi # load TOS2 ptr
movl 16(%ebp), %eax # address of ca routine
pcmpeqw %mm3, %mm3 # load 1 reg
call *%eax # TOS = 32x2 cell result
dup # push %mm0 to memory
movl (%esi), %eax
movl 4(%esi), %edx
lea 16(%esi), %esi # discard stack
movl %esi, (%edi) # store for stack underflow check
emms
pop %edi
pop %esi
leave
ret
- Previous message: [PD-cvs] externals/pdp/puredata CONTENTS, 1.2, 1.3 Makefile, 1.2, 1.3 pdp_base.c, 1.2, 1.3 pdp_comm.c, 1.2, 1.3 pdp_compat.c, 1.2, 1.3 pdp_control.c, 1.2, 1.3 pdp_dpd_base.c, 1.2, 1.3 pdp_imagebase.c, 1.2, 1.3 pdp_queue.c, 1.2, 1.3 pdp_ut.c, 1.2, 1.3
- Next message: [PD-cvs] externals/pdp/scaf COPYING, 1.4, 1.5 Makefile, 1.5, 1.6 Makefile.config, 1.5, 1.6 Makefile.config.in, 1.4, 1.5 README, 1.5, 1.6 README.scaf, 1.4, 1.5 TODO, 1.4, 1.5 configure, 1.2, 1.3 configure.ac, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Pd-cvs
mailing list