annotate audioDB.cpp @ 277:abfb26e08d9c audiodb-debian

Merge trunk changes -r326:386 into audiodb-debian branch. Plus new debian/changelog version. (Should have used an epoch really, but couldn't be bothered; TODO: work out a sane version numbering policy).
author mas01cr
date Tue, 01 Jul 2008 09:12:40 +0000
parents 15b8ff55ea5b
children
rev   line source
mas01cr@0 1 #include "audioDB.h"
mas01cr@0 2
mas01cr@78 3 audioDB::audioDB(const unsigned argc, char* const argv[]): O2_AUDIODB_INITIALIZERS
mas01cr@78 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@167 14 error("No command found");
mas01cr@0 15 }
mas01cr@78 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@78 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@195 44 else if(O2_ACTION(COM_POWER))
mas01cr@195 45 power_flag(dbName);
mas01cr@195 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@136 54 audioDB::audioDB(const unsigned argc, char* const argv[], adb__queryResponse *adbQueryResponse): O2_AUDIODB_INITIALIZERS
mas01cr@78 55 {
mas01cr@107 56 try {
mas01cr@167 57 isServer = 1; // FIXME: Hack
mas01cr@107 58 processArgs(argc, argv);
mas01cr@107 59 assert(O2_ACTION(COM_QUERY));
mas01cr@136 60 query(dbName, inFile, adbQueryResponse);
mas01cr@107 61 } catch(char *err) {
mas01cr@107 62 cleanup();
mas01cr@107 63 throw(err);
mas01cr@107 64 }
mas01cr@78 65 }
mas01cr@78 66
mas01cr@136 67 audioDB::audioDB(const unsigned argc, char* const argv[], adb__statusResponse *adbStatusResponse): O2_AUDIODB_INITIALIZERS
mas01cr@78 68 {
mas01cr@107 69 try {
mas01cr@167 70 isServer = 1; // FIXME: Hack
mas01cr@107 71 processArgs(argc, argv);
mas01cr@107 72 assert(O2_ACTION(COM_STATUS));
mas01cr@136 73 status(dbName, adbStatusResponse);
mas01cr@107 74 } catch(char *err) {
mas01cr@107 75 cleanup();
mas01cr@107 76 throw(err);
mas01cr@107 77 }
mas01cr@78 78 }
mas01cr@78 79
mas01cr@107 80 void audioDB::cleanup() {
mas01cr@123 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@197 85 munmap(db,getpagesize());
mas01cr@197 86 if(fileTable)
mas01cr@197 87 munmap(fileTable, fileTableLength);
mas01cr@197 88 if(trackTable)
mas01cr@197 89 munmap(trackTable, trackTableLength);
mas01cr@197 90 if(dataBuf)
mas01cr@197 91 munmap(dataBuf, dataBufLength);
mas01cr@197 92 if(timesTable)
mas01cr@197 93 munmap(timesTable, timesTableLength);
mas01cr@197 94 if(l2normTable)
mas01cr@197 95 munmap(l2normTable, l2normTableLength);
mas01cr@197 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@107 105 audioDB::~audioDB(){
mas01cr@107 106 cleanup();
mas01cr@107 107 }
mas01cr@107 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@167 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@243 131 verbosity = args_info.verbosity_arg;
mas01cr@243 132 if(verbosity < 0 || verbosity > 10){
mas01cr@243 133 std::cerr << "Warning: verbosity out of range, setting to 1" << std::endl;
mas01cr@243 134 verbosity = 1;
mas01cr@0 135 }
mas01cr@0 136 }
mas01cr@0 137
mas01cr@136 138 if(args_info.size_given) {
mas01cr@277 139 if(args_info.datasize_given) {
mas01cr@277 140 error("both --size and --datasize given", "");
mas01cr@277 141 }
mas01cr@277 142 if(args_info.ntracks_given) {
mas01cr@277 143 error("both --size and --ntracks given", "");
mas01cr@277 144 }
mas01cr@277 145 if(args_info.datadim_given) {
mas01cr@277 146 error("both --size and --datadim given", "");
mas01cr@277 147 }
mas01cr@197 148 if (args_info.size_arg < 50 || args_info.size_arg > 32000) {
mas01cr@136 149 error("Size out of range", "");
mas01cr@136 150 }
mas01cr@277 151 double ratio = (double) args_info.size_arg * 1000000 / ((double) O2_DEFAULTDBSIZE);
mas01cr@277 152 /* FIXME: what's the safe way of doing this? */
mas01cr@277 153 datasize = (unsigned int) ceil(datasize * ratio);
mas01cr@277 154 ntracks = (unsigned int) ceil(ntracks * ratio);
mas01cr@277 155 } else {
mas01cr@277 156 if(args_info.datasize_given) {
mas01cr@277 157 datasize = args_info.datasize_arg;
mas01cr@277 158 }
mas01cr@277 159 if(args_info.ntracks_given) {
mas01cr@277 160 ntracks = args_info.ntracks_arg;
mas01cr@277 161 }
mas01cr@277 162 if(args_info.datadim_given) {
mas01cr@277 163 datadim = args_info.datadim_arg;
mas01cr@277 164 }
mas01cr@136 165 }
mas01cr@136 166
mas01cr@243 167 if(args_info.radius_given) {
mas01cr@243 168 radius = args_info.radius_arg;
mas01cr@243 169 if(radius <= 0 || radius > 1000000000) {
mas01cr@78 170 error("radius out of range");
mas01cr@243 171 } else {
mas01cr@243 172 VERB_LOG(3, "Setting radius to %f\n", radius);
mas01cr@23 173 }
mas01cr@23 174 }
mas01cr@23 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@167 181 isServer = 1;
mas01cr@107 182 #if defined(O2_DEBUG)
mas01cr@107 183 struct sigaction sa;
mas01cr@107 184 sa.sa_sigaction = sigterm_action;
mas01cr@107 185 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@107 186 sigaction(SIGTERM, &sa, NULL);
mas01cr@107 187 sa.sa_sigaction = sighup_action;
mas01cr@107 188 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@107 189 sigaction(SIGHUP, &sa, NULL);
mas01cr@107 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@107 195 if(args_info.client_given){
mas01cr@107 196 command=COM_CLIENT;
mas01cr@107 197 hostport=args_info.client_arg;
mas01cr@107 198 isClient=1;
mas01cr@107 199 }
mas01cr@0 200
mas01cr@107 201 if(args_info.NEW_given){
mas01cr@107 202 command=COM_CREATE;
mas01cr@107 203 dbName=args_info.database_arg;
mas01cr@107 204 return 0;
mas01cr@107 205 }
mas01cr@0 206
mas01cr@107 207 if(args_info.STATUS_given){
mas01cr@107 208 command=COM_STATUS;
mas01cr@107 209 dbName=args_info.database_arg;
mas01cr@107 210 return 0;
mas01cr@107 211 }
mas01cr@0 212
mas01cr@107 213 if(args_info.DUMP_given){
mas01cr@107 214 command=COM_DUMP;
mas01cr@107 215 dbName=args_info.database_arg;
mas01cr@136 216 output = args_info.output_arg;
mas01cr@107 217 return 0;
mas01cr@107 218 }
mas01cr@0 219
mas01cr@107 220 if(args_info.L2NORM_given){
mas01cr@107 221 command=COM_L2NORM;
mas01cr@107 222 dbName=args_info.database_arg;
mas01cr@107 223 return 0;
mas01cr@107 224 }
mas01cr@0 225
mas01cr@195 226 if(args_info.POWER_given){
mas01cr@195 227 command=COM_POWER;
mas01cr@195 228 dbName=args_info.database_arg;
mas01cr@195 229 return 0;
mas01cr@195 230 }
mas01cr@195 231
mas01cr@107 232 if(args_info.INSERT_given){
mas01cr@107 233 command=COM_INSERT;
mas01cr@107 234 dbName=args_info.database_arg;
mas01cr@107 235 inFile=args_info.features_arg;
mas01cr@107 236 if(args_info.key_given)
mas01cr@107 237 key=args_info.key_arg;
mas01cr@107 238 if(args_info.times_given){
mas01cr@107 239 timesFileName=args_info.times_arg;
mas01cr@107 240 if(strlen(timesFileName)>0){
mas01cr@243 241 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@107 242 error("Could not open times file for reading", timesFileName);
mas01cr@107 243 usingTimes=1;
mas01cr@107 244 }
mas01cr@107 245 }
mas01cr@195 246 if (args_info.power_given) {
mas01cr@195 247 powerFileName = args_info.power_arg;
mas01cr@195 248 if (strlen(powerFileName) > 0) {
mas01cr@195 249 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@195 250 error("Could not open power file for reading", powerFileName, "open");
mas01cr@195 251 }
mas01cr@195 252 usingPower = 1;
mas01cr@195 253 }
mas01cr@195 254 }
mas01cr@107 255 return 0;
mas01cr@107 256 }
mas01cr@107 257
mas01cr@107 258 if(args_info.BATCHINSERT_given){
mas01cr@107 259 command=COM_BATCHINSERT;
mas01cr@107 260 dbName=args_info.database_arg;
mas01cr@107 261 inFile=args_info.featureList_arg;
mas01cr@107 262 if(args_info.keyList_given)
mas01cr@107 263 key=args_info.keyList_arg; // INCONSISTENT NO CHECK
mas01cr@0 264
mas01cr@107 265 /* TO DO: REPLACE WITH
mas01cr@0 266 if(args_info.keyList_given){
mas01cr@23 267 trackFileName=args_info.keyList_arg;
mas01cr@243 268 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01cr@23 269 error("Could not open keyList file for reading",trackFileName);
mas01cr@0 270 }
mas01cr@0 271 AND UPDATE BATCHINSERT()
mas01cr@107 272 */
mas01cr@107 273
mas01cr@107 274 if(args_info.timesList_given){
mas01cr@107 275 timesFileName=args_info.timesList_arg;
mas01cr@107 276 if(strlen(timesFileName)>0){
mas01cr@243 277 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@107 278 error("Could not open timesList file for reading", timesFileName);
mas01cr@107 279 usingTimes=1;
mas01cr@107 280 }
mas01cr@107 281 }
mas01cr@195 282 if(args_info.powerList_given){
mas01cr@195 283 powerFileName=args_info.powerList_arg;
mas01cr@195 284 if(strlen(powerFileName)>0){
mas01cr@243 285 if(!(powerFile = new std::ifstream(powerFileName,std::ios::in)))
mas01cr@195 286 error("Could not open powerList file for reading", powerFileName);
mas01cr@195 287 usingPower=1;
mas01cr@195 288 }
mas01cr@195 289 }
mas01cr@107 290 return 0;
mas01cr@107 291 }
mas01cr@107 292
mas01cr@107 293 // Query command and arguments
mas01cr@107 294 if(args_info.QUERY_given){
mas01cr@107 295 command=COM_QUERY;
mas01cr@107 296 dbName=args_info.database_arg;
mas01cr@107 297 inFile=args_info.features_arg;
mas01cr@107 298
mas01cr@107 299 if(args_info.keyList_given){
mas01cr@107 300 trackFileName=args_info.keyList_arg;
mas01cr@243 301 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01cr@107 302 error("Could not open keyList file for reading",trackFileName);
mas01cr@107 303 }
mas01cr@107 304
mas01cr@107 305 if(args_info.times_given){
mas01cr@107 306 timesFileName=args_info.times_arg;
mas01cr@107 307 if(strlen(timesFileName)>0){
mas01cr@243 308 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@107 309 error("Could not open times file for reading", timesFileName);
mas01cr@107 310 usingTimes=1;
mas01cr@107 311 }
mas01cr@107 312 }
mas01cr@195 313
mas01cr@195 314 if(args_info.power_given){
mas01cr@195 315 powerFileName=args_info.power_arg;
mas01cr@195 316 if(strlen(powerFileName)>0){
mas01cr@195 317 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@195 318 error("Could not open power file for reading", powerFileName, "open");
mas01cr@195 319 }
mas01cr@195 320 usingPower = 1;
mas01cr@195 321 }
mas01cr@195 322 }
mas01cr@107 323
mas01cr@107 324 // query type
mas01cr@107 325 if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0)
mas01cr@107 326 queryType=O2_TRACK_QUERY;
mas01cr@107 327 else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0)
mas01cr@107 328 queryType=O2_POINT_QUERY;
mas01cr@107 329 else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0)
mas01cr@107 330 queryType=O2_SEQUENCE_QUERY;
mas01cr@277 331 else if(strncmp(args_info.QUERY_arg, "nsequence", MAXSTR)==0)
mas01cr@277 332 queryType=O2_N_SEQUENCE_QUERY;
mas01cr@277 333 else if(strncmp(args_info.QUERY_arg, "onetoonensequence", MAXSTR)==0)
mas01cr@277 334 queryType=O2_ONE_TO_ONE_N_SEQUENCE_QUERY;
mas01cr@107 335 else
mas01cr@107 336 error("unsupported query type",args_info.QUERY_arg);
mas01cr@107 337
mas01cr@107 338 if(!args_info.exhaustive_flag){
mas01cr@107 339 queryPoint = args_info.qpoint_arg;
mas01cr@107 340 usingQueryPoint=1;
mas01cr@107 341 if(queryPoint<0 || queryPoint >10000)
mas01cr@107 342 error("queryPoint out of range: 0 <= queryPoint <= 10000");
mas01cr@107 343 }
mas01cr@107 344
mas01cr@107 345 pointNN = args_info.pointnn_arg;
mas01cr@277 346 if(pointNN < 1 || pointNN > O2_MAXNN) {
mas01cr@277 347 error("pointNN out of range: 1 <= pointNN <= 1000000");
mas01cr@107 348 }
mas01cr@107 349 trackNN = args_info.resultlength_arg;
mas01cr@277 350 if(trackNN < 1 || trackNN > O2_MAXNN) {
mas01cr@277 351 error("resultlength out of range: 1 <= resultlength <= 1000000");
mas01cr@107 352 }
mas01cr@107 353 sequenceLength = args_info.sequencelength_arg;
mas01cr@107 354 if(sequenceLength < 1 || sequenceLength > 1000) {
mas01cr@107 355 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01cr@107 356 }
mas01cr@107 357 sequenceHop = args_info.sequencehop_arg;
mas01cr@107 358 if(sequenceHop < 1 || sequenceHop > 1000) {
mas01cr@107 359 error("seqhop out of range: 1 <= seqhop <= 1000");
mas01cr@107 360 }
mas01cr@195 361
mas01cr@195 362 if (args_info.absolute_threshold_given) {
mas01cr@195 363 if (args_info.absolute_threshold_arg >= 0) {
mas01cr@195 364 error("absolute threshold out of range: should be negative");
mas01cr@195 365 }
mas01cr@195 366 use_absolute_threshold = true;
mas01cr@195 367 absolute_threshold = args_info.absolute_threshold_arg;
mas01cr@195 368 }
mas01cr@195 369 if (args_info.relative_threshold_given) {
mas01cr@195 370 use_relative_threshold = true;
mas01cr@195 371 relative_threshold = args_info.relative_threshold_arg;
mas01cr@195 372 }
mas01cr@107 373 return 0;
mas01cr@107 374 }
mas01cr@107 375 return -1; // no command found
mas01cr@0 376 }
mas01cr@0 377
mas01cr@136 378 void audioDB::status(const char* dbName, adb__statusResponse *adbStatusResponse){
mas01cr@0 379 if(!dbH)
mas01cr@197 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++){
mas01cr@23 385 if(trackTable[k]<sequenceLength){
mas01cr@0 386 dudCount++;
mas01cr@23 387 if(!trackTable[k])
mas01cr@78 388 nullCount++;
mas01cr@0 389 }
mas01cr@0 390 }
mas01cr@78 391
mas01cr@136 392 if(adbStatusResponse == 0) {
mas01cr@78 393
mas01cr@78 394 // Update Header information
mas01cr@243 395 std::cout << "num files:" << dbH->numFiles << std::endl;
mas01cr@243 396 std::cout << "data dim:" << dbH->dim <<std::endl;
mas01cr@78 397 if(dbH->dim>0){
mas01cr@243 398 std::cout << "total vectors:" << dbH->length/(sizeof(double)*dbH->dim)<<std::endl;
mas01cr@243 399 std::cout << "vectors available:" << (dbH->timesTableOffset-(dbH->dataOffset+dbH->length))/(sizeof(double)*dbH->dim) << std::endl;
mas01cr@78 400 }
mas01cr@243 401 std::cout << "total bytes:" << dbH->length << " (" << (100.0*dbH->length)/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << std::endl;
mas01cr@243 402 std::cout << "bytes available:" << dbH->timesTableOffset-(dbH->dataOffset+dbH->length) << " (" <<
mas01cr@243 403 (100.0*(dbH->timesTableOffset-(dbH->dataOffset+dbH->length)))/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << std::endl;
mas01cr@243 404 std::cout << "flags:" << dbH->flags << std::endl;
mas01cr@78 405
mas01cr@243 406 std::cout << "null count: " << nullCount << " small sequence count " << dudCount-nullCount << std::endl;
mas01cr@78 407 } else {
mas01cr@136 408 adbStatusResponse->result.numFiles = dbH->numFiles;
mas01cr@136 409 adbStatusResponse->result.dim = dbH->dim;
mas01cr@136 410 adbStatusResponse->result.length = dbH->length;
mas01cr@136 411 adbStatusResponse->result.dudCount = dudCount;
mas01cr@136 412 adbStatusResponse->result.nullCount = nullCount;
mas01cr@136 413 adbStatusResponse->result.flags = dbH->flags;
mas01cr@78 414 }
mas01cr@0 415 }
mas01cr@0 416
mas01cr@197 417 void audioDB::l2norm(const char* dbName) {
mas01cr@197 418 forWrite = true;
mas01cr@197 419 initTables(dbName, 0);
mas01cr@0 420 if(dbH->length>0){
mas01cr@197 421 /* FIXME: should probably be uint64_t */
mas01cr@0 422 unsigned numVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01cr@197 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@195 430
mas01cr@195 431 void audioDB::power_flag(const char *dbName) {
mas01cr@197 432 forWrite = true;
mas01cr@197 433 initTables(dbName, 0);
mas01cr@195 434 if (dbH->length > 0) {
mas01cr@195 435 error("cannot turn on power storage for non-empty database", dbName);
mas01cr@195 436 }
mas01cr@195 437 dbH->flags |= O2_FLAG_POWER;
mas01cr@195 438 memcpy(db, dbH, O2_HEADERSIZE);
mas01cr@195 439 }
mas01cr@195 440
mas01cr@243 441 // Unit norm block of features
mas01cr@0 442
mas01cr@243 443 /* FIXME: in fact this does not unit norm a block of features, it just
mas01cr@243 444 records the L2 norms somewhere. unitNorm() does in fact unit norm
mas01cr@243 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@78 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@243 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 }
mas01cr@23 471 l2ptr++;
mas01cr@23 472 X+=dim;
mas01cr@0 473 }
mas01cr@0 474 unsigned offset;
mas01cr@107 475 if(append) {
mas01cr@107 476 // FIXME: a hack, a very palpable hack: the vectors have already
mas01cr@107 477 // been inserted, and dbH->length has already been updated. We
mas01cr@107 478 // need to subtract off again the number of vectors that we've
mas01cr@107 479 // inserted this time...
mas01cr@107 480 offset=(dbH->length/(dbH->dim*sizeof(double)))-n; // number of vectors
mas01cr@107 481 } else {
mas01cr@0 482 offset=0;
mas01cr@107 483 }
mas01cr@0 484 memcpy(l2normTable+offset, l2buf, n*sizeof(double));
mas01cr@0 485 if(l2buf)
mas01cr@23 486 delete[] l2buf;
mas01cr@243 487 VERB_LOG(2, " done.");
mas01cr@195 488 }
mas01cr@195 489
mas01cr@0 490 int main(const unsigned argc, char* const argv[]){
mas01cr@0 491 audioDB(argc, argv);
mas01cr@0 492 }