annotate audioDB.cpp @ 263:210b2f661b88

Added new query type "onetoonensequence" for matching each query sequence to the single closest match in the database. Most useful if query is not also in the database.
author mas01mc
date Mon, 09 Jun 2008 19:20:39 +0000
parents 4dcb09f5fe85
children 4ffa05f25a00 3be15407e814
rev   line source
mas01cr@0 1 #include "audioDB.h"
mas01cr@0 2
mas01cr@76 3 audioDB::audioDB(const unsigned argc, char* const argv[]): O2_AUDIODB_INITIALIZERS
mas01cr@76 4 {
mas01cr@0 5 if(processArgs(argc, argv)<0){
mas01cr@0 6 printf("No command found.\n");
mas01cr@0 7 cmdline_parser_print_version ();
mas01cr@0 8 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 9 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 10 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 11 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 12 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 13 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@151 14 error("No command found");
mas01cr@0 15 }
mas01cr@77 16
mas01cr@0 17 if(O2_ACTION(COM_SERVER))
mas01cr@0 18 startServer();
mas01cr@0 19
mas01cr@0 20 else if(O2_ACTION(COM_CREATE))
mas01cr@0 21 create(dbName);
mas01cr@0 22
mas01cr@0 23 else if(O2_ACTION(COM_INSERT))
mas01cr@0 24 insert(dbName, inFile);
mas01cr@0 25
mas01cr@0 26 else if(O2_ACTION(COM_BATCHINSERT))
mas01cr@0 27 batchinsert(dbName, inFile);
mas01cr@0 28
mas01cr@0 29 else if(O2_ACTION(COM_QUERY))
mas01cr@0 30 if(isClient)
mas01cr@0 31 ws_query(dbName, inFile, (char*)hostport);
mas01cr@0 32 else
mas01cr@76 33 query(dbName, inFile);
mas01cr@0 34
mas01cr@0 35 else if(O2_ACTION(COM_STATUS))
mas01cr@0 36 if(isClient)
mas01cr@0 37 ws_status(dbName,(char*)hostport);
mas01cr@0 38 else
mas01cr@0 39 status(dbName);
mas01cr@0 40
mas01cr@0 41 else if(O2_ACTION(COM_L2NORM))
mas01cr@0 42 l2norm(dbName);
mas01cr@0 43
mas01cr@193 44 else if(O2_ACTION(COM_POWER))
mas01cr@193 45 power_flag(dbName);
mas01cr@193 46
mas01cr@0 47 else if(O2_ACTION(COM_DUMP))
mas01cr@0 48 dump(dbName);
mas01cr@0 49
mas01cr@0 50 else
mas01cr@0 51 error("Unrecognized command",command);
mas01cr@0 52 }
mas01cr@0 53
mas01cr@133 54 audioDB::audioDB(const unsigned argc, char* const argv[], adb__queryResponse *adbQueryResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 55 {
mas01cr@97 56 try {
mas01cr@151 57 isServer = 1; // FIXME: Hack
mas01cr@97 58 processArgs(argc, argv);
mas01cr@97 59 assert(O2_ACTION(COM_QUERY));
mas01cr@133 60 query(dbName, inFile, adbQueryResponse);
mas01cr@97 61 } catch(char *err) {
mas01cr@97 62 cleanup();
mas01cr@97 63 throw(err);
mas01cr@97 64 }
mas01cr@76 65 }
mas01cr@76 66
mas01cr@133 67 audioDB::audioDB(const unsigned argc, char* const argv[], adb__statusResponse *adbStatusResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 68 {
mas01cr@97 69 try {
mas01cr@151 70 isServer = 1; // FIXME: Hack
mas01cr@97 71 processArgs(argc, argv);
mas01cr@97 72 assert(O2_ACTION(COM_STATUS));
mas01cr@133 73 status(dbName, adbStatusResponse);
mas01cr@97 74 } catch(char *err) {
mas01cr@97 75 cleanup();
mas01cr@97 76 throw(err);
mas01cr@97 77 }
mas01cr@76 78 }
mas01cr@76 79
mas01cr@97 80 void audioDB::cleanup() {
mas01cr@122 81 cmdline_parser_free(&args_info);
mas01cr@0 82 if(indata)
mas01cr@0 83 munmap(indata,statbuf.st_size);
mas01cr@0 84 if(db)
mas01cr@196 85 munmap(db,getpagesize());
mas01cr@196 86 if(fileTable)
mas01cr@196 87 munmap(fileTable, fileTableLength);
mas01cr@196 88 if(trackTable)
mas01cr@196 89 munmap(trackTable, trackTableLength);
mas01cr@196 90 if(dataBuf)
mas01cr@196 91 munmap(dataBuf, dataBufLength);
mas01cr@196 92 if(timesTable)
mas01cr@196 93 munmap(timesTable, timesTableLength);
mas01cr@196 94 if(l2normTable)
mas01cr@196 95 munmap(l2normTable, l2normTableLength);
mas01cr@196 96
mas01cr@0 97 if(dbfid>0)
mas01cr@0 98 close(dbfid);
mas01cr@0 99 if(infid>0)
mas01cr@0 100 close(infid);
mas01cr@0 101 if(dbH)
mas01cr@0 102 delete dbH;
mas01cr@0 103 }
mas01cr@0 104
mas01cr@97 105 audioDB::~audioDB(){
mas01cr@97 106 cleanup();
mas01cr@97 107 }
mas01cr@97 108
mas01cr@0 109 int audioDB::processArgs(const unsigned argc, char* const argv[]){
mas01cr@0 110
mas01cr@0 111 if(argc<2){
mas01cr@0 112 cmdline_parser_print_version ();
mas01cr@0 113 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 114 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 115 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 116 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 117 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 118 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@0 119 exit(0);
mas01cr@0 120 }
mas01cr@0 121
mas01cr@0 122 if (cmdline_parser (argc, argv, &args_info) != 0)
mas01cr@151 123 error("Error parsing command line");
mas01cr@0 124
mas01cr@0 125 if(args_info.help_given){
mas01cr@0 126 cmdline_parser_print_help();
mas01cr@0 127 exit(0);
mas01cr@0 128 }
mas01cr@0 129
mas01cr@0 130 if(args_info.verbosity_given){
mas01cr@239 131 verbosity = args_info.verbosity_arg;
mas01cr@239 132 if(verbosity < 0 || verbosity > 10){
mas01cr@239 133 std::cerr << "Warning: verbosity out of range, setting to 1" << std::endl;
mas01cr@239 134 verbosity = 1;
mas01cr@0 135 }
mas01cr@0 136 }
mas01cr@0 137
mas01cr@129 138 if(args_info.size_given) {
mas01cr@256 139 if(args_info.datasize_given) {
mas01cr@256 140 error("both --size and --datasize given", "");
mas01cr@256 141 }
mas01cr@256 142 if(args_info.ntracks_given) {
mas01cr@256 143 error("both --size and --ntracks given", "");
mas01cr@256 144 }
mas01cr@256 145 if(args_info.datadim_given) {
mas01cr@256 146 error("both --size and --datadim given", "");
mas01cr@256 147 }
mas01cr@196 148 if (args_info.size_arg < 50 || args_info.size_arg > 32000) {
mas01cr@129 149 error("Size out of range", "");
mas01cr@129 150 }
mas01cr@256 151 double ratio = (double) args_info.size_arg * 1000000 / ((double) O2_DEFAULTDBSIZE);
mas01cr@256 152 /* FIXME: what's the safe way of doing this? */
mas01cr@256 153 datasize = (unsigned int) ceil(datasize * ratio);
mas01cr@256 154 ntracks = (unsigned int) ceil(ntracks * ratio);
mas01cr@256 155 } else {
mas01cr@256 156 if(args_info.datasize_given) {
mas01cr@256 157 datasize = args_info.datasize_arg;
mas01cr@256 158 }
mas01cr@256 159 if(args_info.ntracks_given) {
mas01cr@256 160 ntracks = args_info.ntracks_arg;
mas01cr@256 161 }
mas01cr@256 162 if(args_info.datadim_given) {
mas01cr@256 163 datadim = args_info.datadim_arg;
mas01cr@256 164 }
mas01cr@129 165 }
mas01cr@129 166
mas01cr@239 167 if(args_info.radius_given) {
mas01cr@239 168 radius = args_info.radius_arg;
mas01cr@239 169 if(radius <= 0 || radius > 1000000000) {
mas01cr@77 170 error("radius out of range");
mas01cr@239 171 } else {
mas01cr@239 172 VERB_LOG(3, "Setting radius to %f\n", radius);
mas01mc@17 173 }
mas01mc@17 174 }
mas01mc@17 175
mas01cr@0 176 if(args_info.SERVER_given){
mas01cr@0 177 command=COM_SERVER;
mas01cr@0 178 port=args_info.SERVER_arg;
mas01cr@0 179 if(port<100 || port > 100000)
mas01cr@0 180 error("port out of range");
mas01cr@151 181 isServer = 1;
mas01cr@105 182 #if defined(O2_DEBUG)
mas01cr@104 183 struct sigaction sa;
mas01cr@104 184 sa.sa_sigaction = sigterm_action;
mas01cr@104 185 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 186 sigaction(SIGTERM, &sa, NULL);
mas01cr@104 187 sa.sa_sigaction = sighup_action;
mas01cr@104 188 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 189 sigaction(SIGHUP, &sa, NULL);
mas01cr@105 190 #endif
mas01cr@0 191 return 0;
mas01cr@0 192 }
mas01cr@0 193
mas01cr@0 194 // No return on client command, find database command
mas01cr@105 195 if(args_info.client_given){
mas01cr@105 196 command=COM_CLIENT;
mas01cr@105 197 hostport=args_info.client_arg;
mas01cr@105 198 isClient=1;
mas01cr@105 199 }
mas01cr@0 200
mas01cr@105 201 if(args_info.NEW_given){
mas01cr@105 202 command=COM_CREATE;
mas01cr@105 203 dbName=args_info.database_arg;
mas01cr@105 204 return 0;
mas01cr@105 205 }
mas01cr@0 206
mas01cr@105 207 if(args_info.STATUS_given){
mas01cr@105 208 command=COM_STATUS;
mas01cr@105 209 dbName=args_info.database_arg;
mas01cr@105 210 return 0;
mas01cr@105 211 }
mas01cr@0 212
mas01cr@105 213 if(args_info.DUMP_given){
mas01cr@105 214 command=COM_DUMP;
mas01cr@105 215 dbName=args_info.database_arg;
mas01cr@131 216 output = args_info.output_arg;
mas01cr@105 217 return 0;
mas01cr@105 218 }
mas01cr@0 219
mas01cr@105 220 if(args_info.L2NORM_given){
mas01cr@105 221 command=COM_L2NORM;
mas01cr@105 222 dbName=args_info.database_arg;
mas01cr@105 223 return 0;
mas01cr@105 224 }
mas01cr@0 225
mas01cr@193 226 if(args_info.POWER_given){
mas01cr@193 227 command=COM_POWER;
mas01cr@193 228 dbName=args_info.database_arg;
mas01cr@193 229 return 0;
mas01cr@193 230 }
mas01cr@193 231
mas01cr@105 232 if(args_info.INSERT_given){
mas01cr@105 233 command=COM_INSERT;
mas01cr@105 234 dbName=args_info.database_arg;
mas01cr@105 235 inFile=args_info.features_arg;
mas01cr@105 236 if(args_info.key_given)
mas01cr@105 237 key=args_info.key_arg;
mas01cr@105 238 if(args_info.times_given){
mas01cr@105 239 timesFileName=args_info.times_arg;
mas01cr@105 240 if(strlen(timesFileName)>0){
mas01cr@239 241 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 242 error("Could not open times file for reading", timesFileName);
mas01cr@105 243 usingTimes=1;
mas01cr@105 244 }
mas01cr@105 245 }
mas01cr@193 246 if (args_info.power_given) {
mas01cr@193 247 powerFileName = args_info.power_arg;
mas01cr@193 248 if (strlen(powerFileName) > 0) {
mas01cr@193 249 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@193 250 error("Could not open power file for reading", powerFileName, "open");
mas01cr@193 251 }
mas01cr@193 252 usingPower = 1;
mas01cr@193 253 }
mas01cr@193 254 }
mas01cr@105 255 return 0;
mas01cr@105 256 }
mas01cr@105 257
mas01cr@105 258 if(args_info.BATCHINSERT_given){
mas01cr@105 259 command=COM_BATCHINSERT;
mas01cr@105 260 dbName=args_info.database_arg;
mas01cr@105 261 inFile=args_info.featureList_arg;
mas01cr@105 262 if(args_info.keyList_given)
mas01cr@105 263 key=args_info.keyList_arg; // INCONSISTENT NO CHECK
mas01cr@0 264
mas01cr@105 265 /* TO DO: REPLACE WITH
mas01cr@0 266 if(args_info.keyList_given){
mas01mc@18 267 trackFileName=args_info.keyList_arg;
mas01cr@239 268 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01mc@18 269 error("Could not open keyList file for reading",trackFileName);
mas01cr@0 270 }
mas01cr@0 271 AND UPDATE BATCHINSERT()
mas01cr@105 272 */
mas01cr@105 273
mas01cr@105 274 if(args_info.timesList_given){
mas01cr@105 275 timesFileName=args_info.timesList_arg;
mas01cr@105 276 if(strlen(timesFileName)>0){
mas01cr@239 277 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 278 error("Could not open timesList file for reading", timesFileName);
mas01cr@105 279 usingTimes=1;
mas01cr@105 280 }
mas01cr@105 281 }
mas01cr@193 282 if(args_info.powerList_given){
mas01cr@193 283 powerFileName=args_info.powerList_arg;
mas01cr@193 284 if(strlen(powerFileName)>0){
mas01cr@239 285 if(!(powerFile = new std::ifstream(powerFileName,std::ios::in)))
mas01cr@193 286 error("Could not open powerList file for reading", powerFileName);
mas01cr@193 287 usingPower=1;
mas01cr@193 288 }
mas01cr@193 289 }
mas01cr@105 290 return 0;
mas01cr@105 291 }
mas01cr@105 292
mas01cr@105 293 // Query command and arguments
mas01cr@105 294 if(args_info.QUERY_given){
mas01cr@105 295 command=COM_QUERY;
mas01cr@105 296 dbName=args_info.database_arg;
mas01cr@105 297 inFile=args_info.features_arg;
mas01cr@105 298
mas01cr@105 299 if(args_info.keyList_given){
mas01cr@105 300 trackFileName=args_info.keyList_arg;
mas01cr@239 301 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01cr@105 302 error("Could not open keyList file for reading",trackFileName);
mas01cr@105 303 }
mas01cr@105 304
mas01cr@105 305 if(args_info.times_given){
mas01cr@105 306 timesFileName=args_info.times_arg;
mas01cr@105 307 if(strlen(timesFileName)>0){
mas01cr@239 308 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 309 error("Could not open times file for reading", timesFileName);
mas01cr@105 310 usingTimes=1;
mas01cr@105 311 }
mas01cr@105 312 }
mas01cr@193 313
mas01cr@193 314 if(args_info.power_given){
mas01cr@193 315 powerFileName=args_info.power_arg;
mas01cr@193 316 if(strlen(powerFileName)>0){
mas01cr@193 317 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@193 318 error("Could not open power file for reading", powerFileName, "open");
mas01cr@193 319 }
mas01cr@193 320 usingPower = 1;
mas01cr@193 321 }
mas01cr@193 322 }
mas01cr@105 323
mas01cr@105 324 // query type
mas01cr@105 325 if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0)
mas01cr@105 326 queryType=O2_TRACK_QUERY;
mas01cr@105 327 else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0)
mas01cr@105 328 queryType=O2_POINT_QUERY;
mas01cr@105 329 else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0)
mas01cr@105 330 queryType=O2_SEQUENCE_QUERY;
mas01mc@248 331 else if(strncmp(args_info.QUERY_arg, "nsequence", MAXSTR)==0)
mas01mc@248 332 queryType=O2_N_SEQUENCE_QUERY;
mas01mc@263 333 else if(strncmp(args_info.QUERY_arg, "onetoonensequence", MAXSTR)==0)
mas01mc@263 334 queryType=O2_ONE_TO_ONE_N_SEQUENCE_QUERY;
mas01cr@105 335 else
mas01cr@105 336 error("unsupported query type",args_info.QUERY_arg);
mas01cr@105 337
mas01cr@105 338 if(!args_info.exhaustive_flag){
mas01cr@105 339 queryPoint = args_info.qpoint_arg;
mas01cr@105 340 usingQueryPoint=1;
mas01cr@105 341 if(queryPoint<0 || queryPoint >10000)
mas01cr@105 342 error("queryPoint out of range: 0 <= queryPoint <= 10000");
mas01cr@105 343 }
mas01cr@105 344
mas01cr@105 345 pointNN = args_info.pointnn_arg;
mas01mc@263 346 if(pointNN < 1 || pointNN > O2_MAXNN) {
mas01mc@263 347 error("pointNN out of range: 1 <= pointNN <= 1000000");
mas01cr@105 348 }
mas01cr@105 349 trackNN = args_info.resultlength_arg;
mas01mc@263 350 if(trackNN < 1 || trackNN > O2_MAXNN) {
mas01mc@263 351 error("resultlength out of range: 1 <= resultlength <= 1000000");
mas01cr@105 352 }
mas01cr@105 353 sequenceLength = args_info.sequencelength_arg;
mas01cr@105 354 if(sequenceLength < 1 || sequenceLength > 1000) {
mas01cr@105 355 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01cr@105 356 }
mas01cr@105 357 sequenceHop = args_info.sequencehop_arg;
mas01cr@105 358 if(sequenceHop < 1 || sequenceHop > 1000) {
mas01cr@105 359 error("seqhop out of range: 1 <= seqhop <= 1000");
mas01cr@105 360 }
mas01cr@193 361
mas01cr@193 362 if (args_info.absolute_threshold_given) {
mas01cr@193 363 if (args_info.absolute_threshold_arg >= 0) {
mas01cr@193 364 error("absolute threshold out of range: should be negative");
mas01cr@193 365 }
mas01cr@193 366 use_absolute_threshold = true;
mas01cr@193 367 absolute_threshold = args_info.absolute_threshold_arg;
mas01cr@193 368 }
mas01cr@193 369 if (args_info.relative_threshold_given) {
mas01cr@193 370 use_relative_threshold = true;
mas01cr@193 371 relative_threshold = args_info.relative_threshold_arg;
mas01cr@193 372 }
mas01cr@105 373 return 0;
mas01cr@105 374 }
mas01cr@105 375 return -1; // no command found
mas01cr@0 376 }
mas01cr@0 377
mas01cr@133 378 void audioDB::status(const char* dbName, adb__statusResponse *adbStatusResponse){
mas01cr@0 379 if(!dbH)
mas01cr@196 380 initTables(dbName, 0);
mas01cr@0 381
mas01cr@0 382 unsigned dudCount=0;
mas01cr@0 383 unsigned nullCount=0;
mas01cr@0 384 for(unsigned k=0; k<dbH->numFiles; k++){
mas01mc@18 385 if(trackTable[k]<sequenceLength){
mas01cr@0 386 dudCount++;
mas01mc@18 387 if(!trackTable[k])
mas01cr@76 388 nullCount++;
mas01cr@0 389 }
mas01cr@0 390 }
mas01cr@76 391
mas01cr@133 392 if(adbStatusResponse == 0) {
mas01cr@76 393
mas01cr@76 394 // Update Header information
mas01cr@239 395 std::cout << "num files:" << dbH->numFiles << std::endl;
mas01cr@239 396 std::cout << "data dim:" << dbH->dim <<std::endl;
mas01cr@76 397 if(dbH->dim>0){
mas01cr@239 398 std::cout << "total vectors:" << dbH->length/(sizeof(double)*dbH->dim)<<std::endl;
mas01cr@239 399 std::cout << "vectors available:" << (dbH->timesTableOffset-(dbH->dataOffset+dbH->length))/(sizeof(double)*dbH->dim) << std::endl;
mas01cr@76 400 }
mas01cr@239 401 std::cout << "total bytes:" << dbH->length << " (" << (100.0*dbH->length)/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << std::endl;
mas01cr@239 402 std::cout << "bytes available:" << dbH->timesTableOffset-(dbH->dataOffset+dbH->length) << " (" <<
mas01cr@239 403 (100.0*(dbH->timesTableOffset-(dbH->dataOffset+dbH->length)))/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << std::endl;
mas01cr@239 404 std::cout << "flags:" << dbH->flags << std::endl;
mas01cr@76 405
mas01cr@239 406 std::cout << "null count: " << nullCount << " small sequence count " << dudCount-nullCount << std::endl;
mas01cr@76 407 } else {
mas01cr@133 408 adbStatusResponse->result.numFiles = dbH->numFiles;
mas01cr@133 409 adbStatusResponse->result.dim = dbH->dim;
mas01cr@133 410 adbStatusResponse->result.length = dbH->length;
mas01cr@133 411 adbStatusResponse->result.dudCount = dudCount;
mas01cr@133 412 adbStatusResponse->result.nullCount = nullCount;
mas01cr@133 413 adbStatusResponse->result.flags = dbH->flags;
mas01cr@76 414 }
mas01cr@0 415 }
mas01cr@0 416
mas01cr@196 417 void audioDB::l2norm(const char* dbName) {
mas01cr@196 418 forWrite = true;
mas01cr@196 419 initTables(dbName, 0);
mas01cr@0 420 if(dbH->length>0){
mas01cr@196 421 /* FIXME: should probably be uint64_t */
mas01cr@0 422 unsigned numVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01cr@196 423 CHECKED_MMAP(double *, dataBuf, dbH->dataOffset, dataBufLength);
mas01cr@0 424 unitNormAndInsertL2(dataBuf, dbH->dim, numVectors, 0); // No append
mas01cr@0 425 }
mas01cr@0 426 // Update database flags
mas01cr@0 427 dbH->flags = dbH->flags|O2_FLAG_L2NORM;
mas01cr@0 428 memcpy (db, dbH, O2_HEADERSIZE);
mas01cr@0 429 }
mas01cr@193 430
mas01cr@193 431 void audioDB::power_flag(const char *dbName) {
mas01cr@196 432 forWrite = true;
mas01cr@196 433 initTables(dbName, 0);
mas01cr@193 434 if (dbH->length > 0) {
mas01cr@193 435 error("cannot turn on power storage for non-empty database", dbName);
mas01cr@193 436 }
mas01cr@193 437 dbH->flags |= O2_FLAG_POWER;
mas01cr@193 438 memcpy(db, dbH, O2_HEADERSIZE);
mas01cr@193 439 }
mas01cr@193 440
mas01cr@239 441 // Unit norm block of features
mas01cr@0 442
mas01cr@239 443 /* FIXME: in fact this does not unit norm a block of features, it just
mas01cr@239 444 records the L2 norms somewhere. unitNorm() does in fact unit norm
mas01cr@239 445 a block of features. */
mas01cr@0 446 void audioDB::unitNormAndInsertL2(double* X, unsigned dim, unsigned n, unsigned append=0){
mas01cr@0 447 unsigned d;
mas01cr@59 448 double *p;
mas01cr@0 449 unsigned nn = n;
mas01cr@0 450
mas01cr@0 451 assert(l2normTable);
mas01cr@0 452
mas01cr@0 453 if( !append && (dbH->flags & O2_FLAG_L2NORM) )
mas01cr@0 454 error("Database is already L2 normed", "automatic norm on insert is enabled");
mas01cr@0 455
mas01cr@239 456 VERB_LOG(2, "norming %u vectors...", n);
mas01cr@0 457
mas01cr@0 458 double* l2buf = new double[n];
mas01cr@0 459 double* l2ptr = l2buf;
mas01cr@0 460 assert(l2buf);
mas01cr@0 461 assert(X);
mas01cr@0 462
mas01cr@0 463 while(nn--){
mas01cr@0 464 p=X;
mas01cr@0 465 *l2ptr=0.0;
mas01cr@0 466 d=dim;
mas01cr@0 467 while(d--){
mas01cr@0 468 *l2ptr+=*p**p;
mas01cr@0 469 p++;
mas01cr@0 470 }
mas01mc@17 471 l2ptr++;
mas01mc@17 472 X+=dim;
mas01cr@0 473 }
mas01cr@0 474 unsigned offset;
mas01cr@84 475 if(append) {
mas01cr@84 476 // FIXME: a hack, a very palpable hack: the vectors have already
mas01cr@84 477 // been inserted, and dbH->length has already been updated. We
mas01cr@84 478 // need to subtract off again the number of vectors that we've
mas01cr@84 479 // inserted this time...
mas01cr@84 480 offset=(dbH->length/(dbH->dim*sizeof(double)))-n; // number of vectors
mas01cr@84 481 } else {
mas01cr@0 482 offset=0;
mas01cr@84 483 }
mas01cr@0 484 memcpy(l2normTable+offset, l2buf, n*sizeof(double));
mas01cr@0 485 if(l2buf)
mas01mc@17 486 delete[] l2buf;
mas01cr@239 487 VERB_LOG(2, " done.");
mas01cr@193 488 }
mas01cr@193 489
mas01cr@0 490 int main(const unsigned argc, char* const argv[]){
mas01cr@0 491 audioDB(argc, argv);
mas01cr@0 492 }