Mercurial > hg > audiodb
changeset 569:327fd3aa17e6
Shifted the query type condition into setquerytype, so it's no longer
stored as a string. Also did some rejigging to get the tabs consistent,
and added some comments for a few less obvious areas of code.
author | mas01mj |
---|---|
date | Wed, 01 Jul 2009 11:44:55 +0000 |
parents | 7a257a2364a4 |
children | d1456b3f490a |
files | bindings/pd/adbpd.c |
diffstat | 1 files changed, 226 insertions(+), 227 deletions(-) [+] |
line wrap: on
line diff
--- a/bindings/pd/adbpd.c Wed Jul 01 11:44:49 2009 +0000 +++ b/bindings/pd/adbpd.c Wed Jul 01 11:44:55 2009 +0000 @@ -30,18 +30,18 @@ t_outlet *x_qpos; t_outlet *x_spos; - t_symbol *x_dbname; //database name + t_symbol *x_dbname; //database name - t_symbol *x_dbquerytype; //sequence, track, etc. - t_symbol *x_dbfeature; + t_int x_dbquerytype; //sequence, track, etc. + t_symbol *x_dbfeature; // t_symbol *x_dbpower; - t_symbol *x_dbkey; - t_float x_dbqpoint; - t_float x_dbnumpoints; - t_float x_dbradius; - t_float x_dbresultlength; - t_float x_dbsequencelength; - adb_ptr db; + t_symbol *x_dbkey; + t_float x_dbqpoint; + t_float x_dbnumpoints; + t_float x_dbradius; + t_float x_dbresultlength; + t_float x_dbsequencelength; + adb_ptr db; } t_adbpd; @@ -86,56 +86,54 @@ x->x_qpos = outlet_new(&x->x_obj, &s_float); x->x_spos = outlet_new(&x->x_obj, &s_float); - /* adb defaults. These are the same but we need to init them */ - x->x_dbname=gensym("no db has been specified yet"); - x->x_dbquerytype=gensym("point"); - x->x_dbfeature=gensym("No feature file yet specified"); - x->x_dbqpoint=1; - x->x_dbnumpoints=10; - x->x_dbradius=1; - x->x_dbresultlength=10; - x->x_dbsequencelength=12; + /* adb defaults. These are the same but we need to init them */ + x->x_dbname=gensym("no db has been specified yet"); + x->x_dbquerytype=O2_POINT_QUERY; + x->x_dbfeature=gensym("No feature file yet specified"); + x->x_dbqpoint=1; + x->x_dbnumpoints=10; + x->x_dbradius=1; + x->x_dbresultlength=10; + x->x_dbsequencelength=12; return(x); - + } - - /* bang just gets the status of the db */ static void adbpd_bang(t_adbpd *x) { - adbpd_doquery(x); + adbpd_doquery(x); } /* create a database */ static void adbpd_create(t_adbpd *x){ - post("creating db '%s'",x->x_dbname->s_name); - dbpointer=audiodb_create(x->x_dbname->s_name,0,0,0); - - if (dbpointer){ - post("Created"); - x->db=dbpointer; - } else { - error("Could not create db. May already exist"); - x->db=NULL; - } + post("creating db '%s'",x->x_dbname->s_name); + dbpointer=audiodb_create(x->x_dbname->s_name,0,0,0); + + if (dbpointer){ + post("Created"); + x->db=dbpointer; + } else { + error("Could not create db. May already exist"); + x->db=NULL; + } } /* open a database. Need to work out the path stuff here. At present databases need to be in the root directory. Not good. */ static void adbpd_open(t_adbpd *x){ - post("Opening db '%s'",x->x_dbname->s_name); - dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR); - - if (dbpointer){ - post("Opened db"); - x->db=dbpointer; - } else { - error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name); - x->db=NULL; - } + post("Opening db '%s'",x->x_dbname->s_name); + dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR); + + if (dbpointer){ + post("Opened db"); + x->db=dbpointer; + } else { + error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name); + x->db=NULL; + } } @@ -143,205 +141,192 @@ static void adbpd_setname(t_adbpd *x, t_symbol *s, int argc, t_atom *argv){ /* if we have a properly formed instruction */ - if (argc == 1 && argv->a_type == A_SYMBOL){ - x->x_dbname=gensym(argv->a_w.w_symbol->s_name); /* make the internal database reference name the same as the name of the database we want. - This is stupid. There must be a better way of doing this. */ - post("Name has been set to '%s', and can now be opened.",x->x_dbname->s_name); - } + if (argc == 1 && argv->a_type == A_SYMBOL){ + x->x_dbname=gensym(argv->a_w.w_symbol->s_name); /* make the internal database reference name the same as the name of the database we want. + This is stupid. There must be a better way of doing this. */ + post("Name has been set to '%s', and can now be opened.",x->x_dbname->s_name); + } /* now we can open the database as we did with the audiodb_open call above*/ post("Opening db '%s'",x->x_dbname->s_name); - dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR); /* opened in read and write mode for when I get round to doing the insert code */ + dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR); /* opened in read and write mode for when I get round to doing the insert code */ - if (dbpointer){ /* yes we have a database*/ - post("Opened db"); - x->db=dbpointer; - } else { - error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name); - x->db=NULL; - } + if (dbpointer){ /* yes we have a database*/ + post("Opened db"); + x->db=dbpointer; + } else { + error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name); + x->db=NULL; + } } /* this is a status call to the audioDB API */ static void adbpd_status(t_adbpd *x){ - adb_status_t mystatus; - - post("Getting Status"); - - if (x->db && !(audiodb_status(x->db,&mystatus))){ - post("numFiles %d",mystatus.numFiles); - post("dim %d",mystatus.dim); - post("length %d",mystatus.length); - post("dudCount %d",mystatus.dudCount); - post("numCount %d",mystatus.nullCount); - post("flags %d",mystatus.flags); - post("Bytes Available %d",mystatus.data_region_size); - } else { - error("Can't get Status. Have you selected a db?"); - } + adb_status_t mystatus; + + post("Getting Status"); + + if (x->db && !(audiodb_status(x->db,&mystatus))){ + post("numFiles %d",mystatus.numFiles); + post("dim %d",mystatus.dim); + post("length %d",mystatus.length); + post("dudCount %d",mystatus.dudCount); + post("numCount %d",mystatus.nullCount); + post("flags %d",mystatus.flags); + post("Bytes Available %d",mystatus.data_region_size); + } else { + error("Can't get Status. Have you selected a db?"); + } } static void adbpd_doquery(t_adbpd *x){ - adb_datum_t datum = {0}; - adb_query_id_t qid = {0}; - adb_query_parameters_t params = {0}; - adb_query_refine_t refine = {0}; - adb_query_spec_t spec = {0}; - - qid.datum = &datum; - qid.sequence_length = x->x_dbsequencelength; - qid.sequence_start = x->x_dbqpoint; - qid.flags = 0; + adb_datum_t datum = {0}; + adb_query_id_t qid = {0}; + adb_query_parameters_t params = {0}; + adb_query_refine_t refine = {0}; + adb_query_spec_t spec = {0}; + + // Configure the start+length of the query, and zero + // the flags initially. + qid.datum = &datum; + qid.sequence_length = x->x_dbsequencelength; + qid.sequence_start = x->x_dbqpoint; + qid.flags = 0; - refine.hopsize = 1; - refine.flags |= ADB_REFINE_RADIUS; - refine.radius = x->x_dbradius; + // We don't specify hopsize (yet) so it defaults to 1. + refine.hopsize = 1; + refine.flags |= ADB_REFINE_RADIUS; + refine.radius = x->x_dbradius; - spec.qid = qid; - spec.params = params; - spec.refine = refine; + spec.qid = qid; + spec.params = params; + spec.refine = refine; + + int fd; + struct stat st; + + // Read in the feature file - note that this code may contain leaks + // (the same chunk also exists in audioDB.cpp). + fd = open(x->x_dbfeature->s_name, O_RDONLY); + if(fd < 0) { + error("failed to open feature file", x->x_dbfeature->s_name); + return; + } + fstat(fd, &st); + read(fd, &datum.dim, sizeof(uint32_t)); + datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double)); + datum.data = (double *) malloc(st.st_size - sizeof(uint32_t)); + read(fd, datum.data, st.st_size - sizeof(uint32_t)); + close(fd); + + // Set up query spec params depending on the query type. + switch(x->x_dbquerytype) + { + case O2_POINT_QUERY: + spec.qid.sequence_length = 1; + spec.params.accumulation = ADB_ACCUMULATION_DB; + spec.params.distance = ADB_DISTANCE_DOT_PRODUCT; + spec.params.npoints = x->x_dbnumpoints; + spec.params.ntracks = x->x_dbresultlength; + break; + case O2_TRACK_QUERY: + spec.qid.sequence_length = 1; + spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK; + spec.params.distance = ADB_DISTANCE_DOT_PRODUCT; + spec.params.npoints = x->x_dbnumpoints; + spec.params.ntracks = x->x_dbresultlength; + case O2_SEQUENCE_QUERY: + case O2_N_SEQUENCE_QUERY: + spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK; + // TODO : Add unit norming param. Defaults to false. + // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED; + spec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; + spec.params.npoints = x->x_dbnumpoints; + spec.params.ntracks = x->x_dbresultlength; + break; + case O2_ONE_TO_ONE_N_SEQUENCE_QUERY: + spec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE; + // TODO : Add unit norming param. Defaults to false. + // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED; + spec.params.distance =ADB_DISTANCE_EUCLIDEAN_NORMED; + spec.params.npoints = 0; + spec.params.ntracks = 0; + break; + default: + post("Unsupported query type"); + } + + adb_query_results_t *rs = audiodb_query_spec(x->db, &spec); + + if(datum.data) { + free(datum.data); + datum.data = NULL; + } + if(datum.power) { + free(datum.data); + datum.data = NULL; + } + if(datum.times) { + free(datum.data); + datum.data = NULL; + } + + if(rs == NULL) + { + error("Query failed"); + return; + } + + int size = rs->nresults; + post("result size:[%d]",(int)size); + int i = 0; + for(i=0; i<size; i++){ + adb_result_t r = rs->results[i]; - int fd; - struct stat st; - - /* FIXME: around here there are all sorts of hideous leaks. */ - fd = open(x->x_dbfeature->s_name, O_RDONLY); - if(fd < 0) { - error("failed to open feature file", x->x_dbfeature->s_name); - return; - } - fstat(fd, &st); - read(fd, &datum.dim, sizeof(uint32_t)); - datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double)); - datum.data = (double *) malloc(st.st_size - sizeof(uint32_t)); - read(fd, datum.data, st.st_size - sizeof(uint32_t)); - close(fd); + outlet_float(x->x_dist,r.dist); + outlet_float(x->x_qpos,r.qpos); + outlet_float(x->x_spos,r.ipos); - int queryType; - - // query type - if(strncmp(x->x_dbquerytype->s_name, "track", MAXSTR)==0) - queryType=O2_TRACK_QUERY; - else if(strncmp(x->x_dbquerytype->s_name, "point", MAXSTR)==0) - queryType=O2_POINT_QUERY; - else if(strncmp(x->x_dbquerytype->s_name, "sequence", MAXSTR)==0) - queryType=O2_SEQUENCE_QUERY; - else if(strncmp(x->x_dbquerytype->s_name, "nsequence", MAXSTR)==0) - queryType=O2_N_SEQUENCE_QUERY; - else if(strncmp(x->x_dbquerytype->s_name, "onetoonensequence", MAXSTR)==0) - queryType=O2_ONE_TO_ONE_N_SEQUENCE_QUERY; - else - error("unsupported query type"); - - switch(queryType) - { - case O2_POINT_QUERY: - spec.qid.sequence_length = 1; - spec.params.accumulation = ADB_ACCUMULATION_DB; - spec.params.distance = ADB_DISTANCE_DOT_PRODUCT; - spec.params.npoints = x->x_dbnumpoints; - spec.params.ntracks = x->x_dbresultlength; - break; - case O2_TRACK_QUERY: - spec.qid.sequence_length = 1; - spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK; - spec.params.distance = ADB_DISTANCE_DOT_PRODUCT; - spec.params.npoints = x->x_dbnumpoints; - spec.params.ntracks = x->x_dbresultlength; - case O2_SEQUENCE_QUERY: - case O2_N_SEQUENCE_QUERY: - spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK; - // TODO : Add unit norming param. Defaults to false. - // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED; - spec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; - spec.params.npoints = x->x_dbnumpoints; - spec.params.ntracks = x->x_dbresultlength; - break; - case O2_ONE_TO_ONE_N_SEQUENCE_QUERY: - spec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE; - // TODO : Add unit norming param. Defaults to false. - // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED; - spec.params.distance =ADB_DISTANCE_EUCLIDEAN_NORMED; - spec.params.npoints = 0; - spec.params.ntracks = 0; - break; - default: - post("Unsupported query type"); - } - - adb_query_results_t *rs = audiodb_query_spec(x->db, &spec); - - - - if(datum.data) { - free(datum.data); - datum.data = NULL; - } - if(datum.power) { - free(datum.data); - datum.data = NULL; - } - if(datum.times) { - free(datum.data); - datum.data = NULL; - } - - if(rs == NULL) - { - error("Query failed"); - return; - } - - int size = rs->nresults; - post("result size:[%d]",(int)size); - int i = 0; - for(i=0; i<size; i++){ - adb_result_t r = rs->results[i]; - - outlet_float(x->x_dist,r.dist); - outlet_float(x->x_qpos,r.qpos); - outlet_float(x->x_spos,r.ipos); - - post("in obj key:%s",r.key); - post("in obj Dist:%f", r.dist); - post("in obj qpos:%d", r.qpos); - post("in obj ipos:%d", r.ipos); - } + post("in obj key:%s",r.key); + post("in obj Dist:%f", r.dist); + post("in obj qpos:%d", r.qpos); + post("in obj ipos:%d", r.ipos); + } } /* Do I need to set a the power file for this flag to work ? Hmmm. Dunno. Also, should be on/off*/ static void adbpd_power(t_adbpd *x){ - post("power"); - - if (x->db && !(audiodb_power(x->db))){ - post("power successfully set on db"); - } else { - error("power flag not working"); - } + post("power"); + + if (x->db && !(audiodb_power(x->db))){ + post("power successfully set on db"); + } else { + error("power flag not working"); + } } /* works fine but would be better if it took an argument to switch it on and off */ static void adbpd_l2norm(t_adbpd *x){ - post("l2norm"); - - if (x->db && !(audiodb_l2norm(x->db))){ - post("l2norm successfully set on db"); - } else { - error("l2norm flag not working"); - } + post("l2norm"); + + if (x->db && !(audiodb_l2norm(x->db))){ + post("l2norm successfully set on db"); + } else { + error("l2norm flag not working"); + } } /* reports the name of the current db */ static void adbpd_getname(t_adbpd *x){ - post("db name is '%s'", x->x_dbname->s_name); + post("db name is '%s'", x->x_dbname->s_name); } /* this sets the qpoint for the current query*/ @@ -349,7 +334,7 @@ static void adbpd_setqpoint(t_adbpd *x,t_floatarg f){ post("qpoint %.3f",f); - x->x_dbqpoint=f; + x->x_dbqpoint=f; } /* This sets the number of points for current query */ @@ -383,11 +368,11 @@ /* This sets the feature file to use for the query */ static void adbpd_setfeatures(t_adbpd *x,t_symbol *s,int argc, t_atom *argv){ - - if (argc == 1 && argv->a_type == A_SYMBOL){ - x->x_dbfeature=gensym(argv->a_w.w_symbol->s_name); - post("Features file has been set to '%s'",x->x_dbfeature->s_name); - } + + if (argc == 1 && argv->a_type == A_SYMBOL){ + x->x_dbfeature=gensym(argv->a_w.w_symbol->s_name); + post("Features file has been set to '%s'",x->x_dbfeature->s_name); + } } /* This sets the query type */ @@ -395,23 +380,38 @@ static void adbpd_setquerytype(t_adbpd *x,t_symbol *s,int argc, t_atom *argv){ if (argc == 1 && argv->a_type == A_SYMBOL){ - x->x_dbquerytype=gensym(argv->a_w.w_symbol->s_name); - post("Query type has been set to '%s'",x->x_dbquerytype->s_name); - } + + // Determine which constant to use based on the string passed. + + if(strncmp(argv->a_w.w_symbol->s_name, "track", MAXSTR)==0) + x->x_dbquerytype=O2_TRACK_QUERY; + else if(strncmp(argv->a_w.w_symbol->s_name, "point", MAXSTR)==0) + x->x_dbquerytype=O2_POINT_QUERY; + else if(strncmp(argv->a_w.w_symbol->s_name, "sequence", MAXSTR)==0) + x->x_dbquerytype=O2_SEQUENCE_QUERY; + else if(strncmp(argv->a_w.w_symbol->s_name, "nsequence", MAXSTR)==0) + x->x_dbquerytype=O2_N_SEQUENCE_QUERY; + else if(strncmp(argv->a_w.w_symbol->s_name, "onetoonensequence", MAXSTR)==0) + x->x_dbquerytype=O2_ONE_TO_ONE_N_SEQUENCE_QUERY; + else + error("unsupported query type"); + + post("Query type has been set to '%s'",argv->a_w.w_symbol->s_name); + } } /* This lists all the parameters */ static void adbpd_parameters(t_adbpd *x){ - post("dbname %s",x->x_dbname->s_name); - post("querytype %s",x->x_dbquerytype->s_name); - post("features %s",x->x_dbfeature->s_name); - post("qpoint %.3f",x->x_dbqpoint); - post("numpoints %.3f",x->x_dbnumpoints); - post("radius %.3f",x->x_dbradius); - post("resultlength %.3f",x->x_dbresultlength); - post("sequencelength %.3f",x->x_dbsequencelength); + post("dbname %s",x->x_dbname->s_name); + post("querytype %d",x->x_dbquerytype); + post("features %s",x->x_dbfeature->s_name); + post("qpoint %.3f",x->x_dbqpoint); + post("numpoints %.3f",x->x_dbnumpoints); + post("radius %.3f",x->x_dbradius); + post("resultlength %.3f",x->x_dbresultlength); + post("sequencelength %.3f",x->x_dbsequencelength); } /* THAR SHE BLOWS. This sets up the object, takes the messages with args and maps them to methods. */ @@ -434,10 +434,9 @@ class_addmethod(adbpd_class, (t_method)adbpd_l2norm, gensym("l2norm"), A_NULL); class_addmethod(adbpd_class, (t_method)adbpd_power, gensym("power"), A_NULL); class_addmethod(adbpd_class, (t_method)adbpd_doquery, gensym("doquery"), A_NULL); - class_addmethod(adbpd_class, (t_method)adbpd_setquerytype, gensym("querytype"), A_GIMME, 0); - class_addmethod(adbpd_class, (t_method)adbpd_setfeatures, gensym("features"), A_GIMME, 0); + class_addmethod(adbpd_class, (t_method)adbpd_setquerytype, gensym("querytype"), A_GIMME, 0); + class_addmethod(adbpd_class, (t_method)adbpd_setfeatures, gensym("features"), A_GIMME, 0); class_addmethod(adbpd_class, (t_method)adbpd_parameters, gensym("parameters"), A_NULL); - }