annotate audioDB.cpp @ 104:97107ee61dba

Temporary signal handling. "Temporary" because it will not work on platforms which don't have real signals (Hello, Win32) but nevertheless useful, as otherwise gcov (the code coverage tool) will not count executions of processes that are killed by signals (in particular, the server processes started in the tests). A brief experiment suggests that we're up to about 80% statement coverage from our 20 tests.
author mas01cr
date Thu, 04 Oct 2007 15:02:29 +0000
parents 69424e77621f
children 10feb98abebf
rev   line source
mas01cr@0 1 #include "audioDB.h"
mas01cr@0 2
mas01cr@104 3 void sigterm_action(int signal, siginfo_t *info, void *context) {
mas01cr@104 4 exit(128+signal);
mas01cr@104 5 }
mas01cr@104 6
mas01cr@104 7 void sighup_action(int signal, siginfo_t *info, void *context) {
mas01cr@104 8 // FIXME: reread any configuration files
mas01cr@104 9 }
mas01cr@104 10
mas01cr@0 11 #define O2_DEBUG
mas01cr@0 12
mas01cr@32 13 void audioDB::error(const char* a, const char* b, const char *sysFunc) {
mas01cr@77 14 if(isServer) {
mas01cr@81 15 /* FIXME: I think this is leaky -- we never delete err. actually
mas01cr@81 16 deleting it is tricky, though; it gets placed into some
mas01cr@81 17 soap-internal struct with uncertain extent... -- CSR,
mas01cr@81 18 2007-10-01 */
mas01cr@77 19 char *err = new char[256]; /* FIXME: overflows */
mas01cr@77 20 snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : "");
mas01cr@77 21 /* FIXME: actually we could usefully do with a properly structured
mas01cr@77 22 type, so that we can throw separate faultstring and details.
mas01cr@77 23 -- CSR, 2007-10-01 */
mas01cr@77 24 throw(err);
mas01cr@77 25 } else {
mas01cr@77 26 cerr << a << ": " << b << endl;
mas01cr@77 27 if (sysFunc) {
mas01cr@77 28 perror(sysFunc);
mas01cr@77 29 }
mas01cr@77 30 exit(1);
mas01cr@32 31 }
mas01cr@0 32 }
mas01cr@0 33
mas01cr@76 34 #define O2_AUDIODB_INITIALIZERS \
mas01cr@76 35 dim(0), \
mas01cr@76 36 dbName(0), \
mas01cr@76 37 inFile(0), \
mas01cr@76 38 key(0), \
mas01cr@76 39 trackFileName(0), \
mas01cr@76 40 trackFile(0), \
mas01cr@76 41 command(0), \
mas01cr@76 42 timesFileName(0), \
mas01cr@76 43 timesFile(0), \
mas01cr@76 44 dbfid(0), \
mas01cr@76 45 infid(0), \
mas01cr@76 46 db(0), \
mas01cr@76 47 indata(0), \
mas01cr@76 48 dbH(0), \
mas01cr@76 49 fileTable(0), \
mas01cr@76 50 trackTable(0), \
mas01cr@76 51 dataBuf(0), \
mas01cr@76 52 l2normTable(0), \
mas01cr@76 53 qNorm(0), \
mas01cr@76 54 timesTable(0), \
mas01cr@76 55 verbosity(1), \
mas01cr@76 56 queryType(O2_FLAG_POINT_QUERY), \
mas01cr@76 57 pointNN(O2_DEFAULT_POINTNN), \
mas01cr@76 58 trackNN(O2_DEFAULT_TRACKNN), \
mas01cr@76 59 sequenceLength(16), \
mas01cr@76 60 sequenceHop(1), \
mas01cr@76 61 queryPoint(0), \
mas01cr@76 62 usingQueryPoint(0), \
mas01cr@76 63 usingTimes(0), \
mas01cr@76 64 isClient(0), \
mas01cr@76 65 isServer(0), \
mas01cr@76 66 port(0), \
mas01cr@76 67 timesTol(0.1), \
mas01cr@76 68 radius(0)
mas01cr@76 69
mas01cr@76 70 audioDB::audioDB(const unsigned argc, char* const argv[]): O2_AUDIODB_INITIALIZERS
mas01cr@76 71 {
mas01cr@0 72 if(processArgs(argc, argv)<0){
mas01cr@0 73 printf("No command found.\n");
mas01cr@0 74 cmdline_parser_print_version ();
mas01cr@0 75 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 76 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 77 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 78 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 79 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 80 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@0 81 exit(1);
mas01cr@0 82 }
mas01cr@77 83
mas01cr@0 84 if(O2_ACTION(COM_SERVER))
mas01cr@0 85 startServer();
mas01cr@0 86
mas01cr@0 87 else if(O2_ACTION(COM_CREATE))
mas01cr@0 88 create(dbName);
mas01cr@0 89
mas01cr@0 90 else if(O2_ACTION(COM_INSERT))
mas01cr@0 91 insert(dbName, inFile);
mas01cr@0 92
mas01cr@0 93 else if(O2_ACTION(COM_BATCHINSERT))
mas01cr@0 94 batchinsert(dbName, inFile);
mas01cr@0 95
mas01cr@0 96 else if(O2_ACTION(COM_QUERY))
mas01cr@0 97 if(isClient)
mas01cr@0 98 ws_query(dbName, inFile, (char*)hostport);
mas01cr@0 99 else
mas01cr@76 100 query(dbName, inFile);
mas01cr@0 101
mas01cr@0 102 else if(O2_ACTION(COM_STATUS))
mas01cr@0 103 if(isClient)
mas01cr@0 104 ws_status(dbName,(char*)hostport);
mas01cr@0 105 else
mas01cr@0 106 status(dbName);
mas01cr@0 107
mas01cr@0 108 else if(O2_ACTION(COM_L2NORM))
mas01cr@0 109 l2norm(dbName);
mas01cr@0 110
mas01cr@0 111 else if(O2_ACTION(COM_DUMP))
mas01cr@0 112 dump(dbName);
mas01cr@0 113
mas01cr@0 114 else
mas01cr@0 115 error("Unrecognized command",command);
mas01cr@0 116 }
mas01cr@0 117
mas01cr@76 118 audioDB::audioDB(const unsigned argc, char* const argv[], adb__queryResult *adbQueryResult): O2_AUDIODB_INITIALIZERS
mas01cr@76 119 {
mas01cr@97 120 try {
mas01cr@97 121 processArgs(argc, argv);
mas01cr@97 122 isServer = 1; // FIXME: Hack
mas01cr@97 123 assert(O2_ACTION(COM_QUERY));
mas01cr@97 124 query(dbName, inFile, adbQueryResult);
mas01cr@97 125 } catch(char *err) {
mas01cr@97 126 cleanup();
mas01cr@97 127 throw(err);
mas01cr@97 128 }
mas01cr@76 129 }
mas01cr@76 130
mas01cr@76 131 audioDB::audioDB(const unsigned argc, char* const argv[], adb__statusResult *adbStatusResult): O2_AUDIODB_INITIALIZERS
mas01cr@76 132 {
mas01cr@97 133 try {
mas01cr@97 134 processArgs(argc, argv);
mas01cr@97 135 isServer = 1; // FIXME: Hack
mas01cr@97 136 assert(O2_ACTION(COM_STATUS));
mas01cr@97 137 status(dbName, adbStatusResult);
mas01cr@97 138 } catch(char *err) {
mas01cr@97 139 cleanup();
mas01cr@97 140 throw(err);
mas01cr@97 141 }
mas01cr@76 142 }
mas01cr@76 143
mas01cr@97 144 void audioDB::cleanup() {
mas01cr@0 145 if(indata)
mas01cr@0 146 munmap(indata,statbuf.st_size);
mas01cr@0 147 if(db)
mas01cr@0 148 munmap(db,O2_DEFAULTDBSIZE);
mas01cr@0 149 if(dbfid>0)
mas01cr@0 150 close(dbfid);
mas01cr@0 151 if(infid>0)
mas01cr@0 152 close(infid);
mas01cr@0 153 if(dbH)
mas01cr@0 154 delete dbH;
mas01cr@0 155 }
mas01cr@0 156
mas01cr@97 157 audioDB::~audioDB(){
mas01cr@97 158 cleanup();
mas01cr@97 159 }
mas01cr@97 160
mas01cr@0 161 int audioDB::processArgs(const unsigned argc, char* const argv[]){
mas01cr@0 162
mas01cr@0 163 if(argc<2){
mas01cr@0 164 cmdline_parser_print_version ();
mas01cr@0 165 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 166 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 167 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 168 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 169 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 170 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@0 171 exit(0);
mas01cr@0 172 }
mas01cr@0 173
mas01cr@0 174 if (cmdline_parser (argc, argv, &args_info) != 0)
mas01cr@0 175 exit(1) ;
mas01cr@0 176
mas01cr@0 177 if(args_info.help_given){
mas01cr@0 178 cmdline_parser_print_help();
mas01cr@0 179 exit(0);
mas01cr@0 180 }
mas01cr@0 181
mas01cr@0 182 if(args_info.verbosity_given){
mas01cr@0 183 verbosity=args_info.verbosity_arg;
mas01cr@0 184 if(verbosity<0 || verbosity>10){
mas01cr@0 185 cerr << "Warning: verbosity out of range, setting to 1" << endl;
mas01cr@0 186 verbosity=1;
mas01cr@0 187 }
mas01cr@0 188 }
mas01cr@0 189
mas01mc@17 190 if(args_info.radius_given){
mas01mc@17 191 radius=args_info.radius_arg;
mas01mc@17 192 if(radius<=0 || radius>1000000000){
mas01cr@77 193 error("radius out of range");
mas01mc@17 194 }
mas01mc@17 195 else
mas01cr@60 196 if(verbosity>3) {
mas01mc@17 197 cerr << "Setting radius to " << radius << endl;
mas01cr@60 198 }
mas01mc@17 199 }
mas01mc@17 200
mas01cr@0 201 if(args_info.SERVER_given){
mas01cr@0 202 command=COM_SERVER;
mas01cr@0 203 port=args_info.SERVER_arg;
mas01cr@0 204 if(port<100 || port > 100000)
mas01cr@0 205 error("port out of range");
mas01cr@0 206 isServer=1;
mas01cr@104 207 struct sigaction sa;
mas01cr@104 208 sa.sa_sigaction = sigterm_action;
mas01cr@104 209 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 210 sigaction(SIGTERM, &sa, NULL);
mas01cr@104 211 sa.sa_sigaction = sighup_action;
mas01cr@104 212 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 213 sigaction(SIGHUP, &sa, NULL);
mas01cr@0 214 return 0;
mas01cr@0 215 }
mas01cr@0 216
mas01cr@0 217 // No return on client command, find database command
mas01cr@0 218 if(args_info.client_given){
mas01cr@0 219 command=COM_CLIENT;
mas01cr@0 220 hostport=args_info.client_arg;
mas01cr@0 221 isClient=1;
mas01cr@0 222 }
mas01cr@0 223
mas01cr@0 224 if(args_info.NEW_given){
mas01cr@0 225 command=COM_CREATE;
mas01cr@0 226 dbName=args_info.database_arg;
mas01cr@0 227 return 0;
mas01cr@0 228 }
mas01cr@0 229
mas01cr@0 230 if(args_info.STATUS_given){
mas01cr@0 231 command=COM_STATUS;
mas01cr@0 232 dbName=args_info.database_arg;
mas01cr@0 233 return 0;
mas01cr@0 234 }
mas01cr@0 235
mas01cr@0 236 if(args_info.DUMP_given){
mas01cr@0 237 command=COM_DUMP;
mas01cr@0 238 dbName=args_info.database_arg;
mas01cr@0 239 return 0;
mas01cr@0 240 }
mas01cr@0 241
mas01cr@0 242 if(args_info.L2NORM_given){
mas01cr@0 243 command=COM_L2NORM;
mas01cr@0 244 dbName=args_info.database_arg;
mas01cr@0 245 return 0;
mas01cr@0 246 }
mas01cr@0 247
mas01cr@0 248 if(args_info.INSERT_given){
mas01cr@0 249 command=COM_INSERT;
mas01cr@0 250 dbName=args_info.database_arg;
mas01cr@0 251 inFile=args_info.features_arg;
mas01cr@0 252 if(args_info.key_given)
mas01cr@0 253 key=args_info.key_arg;
mas01cr@0 254 if(args_info.times_given){
mas01cr@0 255 timesFileName=args_info.times_arg;
mas01cr@0 256 if(strlen(timesFileName)>0){
mas01cr@0 257 if(!(timesFile = new ifstream(timesFileName,ios::in)))
mas01cr@0 258 error("Could not open times file for reading", timesFileName);
mas01cr@0 259 usingTimes=1;
mas01cr@0 260 }
mas01cr@0 261 }
mas01cr@0 262 return 0;
mas01cr@0 263 }
mas01mc@10 264
mas01cr@0 265 if(args_info.BATCHINSERT_given){
mas01cr@0 266 command=COM_BATCHINSERT;
mas01cr@0 267 dbName=args_info.database_arg;
mas01cr@0 268 inFile=args_info.featureList_arg;
mas01cr@0 269 if(args_info.keyList_given)
mas01cr@0 270 key=args_info.keyList_arg; // INCONSISTENT NO CHECK
mas01cr@0 271
mas01cr@0 272 /* TO DO: REPLACE WITH
mas01cr@0 273 if(args_info.keyList_given){
mas01mc@18 274 trackFileName=args_info.keyList_arg;
mas01mc@18 275 if(strlen(trackFileName)>0 && !(trackFile = new ifstream(trackFileName,ios::in)))
mas01mc@18 276 error("Could not open keyList file for reading",trackFileName);
mas01cr@0 277 }
mas01cr@0 278 AND UPDATE BATCHINSERT()
mas01cr@0 279 */
mas01cr@0 280
mas01cr@0 281 if(args_info.timesList_given){
mas01cr@0 282 timesFileName=args_info.timesList_arg;
mas01cr@0 283 if(strlen(timesFileName)>0){
mas01cr@0 284 if(!(timesFile = new ifstream(timesFileName,ios::in)))
mas01cr@0 285 error("Could not open timesList file for reading", timesFileName);
mas01cr@0 286 usingTimes=1;
mas01cr@0 287 }
mas01cr@0 288 }
mas01cr@0 289 return 0;
mas01cr@0 290 }
mas01cr@0 291
mas01cr@0 292 // Query command and arguments
mas01cr@0 293 if(args_info.QUERY_given){
mas01cr@0 294 command=COM_QUERY;
mas01cr@0 295 dbName=args_info.database_arg;
mas01cr@0 296 inFile=args_info.features_arg;
mas01cr@0 297
mas01cr@0 298 if(args_info.keyList_given){
mas01mc@18 299 trackFileName=args_info.keyList_arg;
mas01mc@18 300 if(strlen(trackFileName)>0 && !(trackFile = new ifstream(trackFileName,ios::in)))
mas01mc@18 301 error("Could not open keyList file for reading",trackFileName);
mas01cr@0 302 }
mas01cr@0 303
mas01cr@0 304 if(args_info.times_given){
mas01cr@0 305 timesFileName=args_info.times_arg;
mas01cr@0 306 if(strlen(timesFileName)>0){
mas01cr@0 307 if(!(timesFile = new ifstream(timesFileName,ios::in)))
mas01cr@0 308 error("Could not open times file for reading", timesFileName);
mas01cr@0 309 usingTimes=1;
mas01cr@0 310 }
mas01cr@0 311 }
mas01cr@0 312
mas01cr@0 313 // query type
mas01mc@18 314 if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0)
mas01mc@18 315 queryType=O2_FLAG_TRACK_QUERY;
mas01cr@0 316 else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0)
mas01cr@0 317 queryType=O2_FLAG_POINT_QUERY;
mas01cr@0 318 else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0)
mas01cr@0 319 queryType=O2_FLAG_SEQUENCE_QUERY;
mas01cr@0 320 else
mas01cr@0 321 error("unsupported query type",args_info.QUERY_arg);
mas01cr@0 322
mas01cr@0 323 if(!args_info.exhaustive_flag){
mas01cr@0 324 queryPoint = args_info.qpoint_arg;
mas01cr@0 325 usingQueryPoint=1;
mas01cr@0 326 if(queryPoint<0 || queryPoint >10000)
mas01cr@0 327 error("queryPoint out of range: 0 <= queryPoint <= 10000");
mas01cr@0 328 }
mas01cr@0 329
mas01cr@0 330
mas01cr@0 331 pointNN=args_info.pointnn_arg;
mas01cr@0 332 if(pointNN<1 || pointNN >1000)
mas01cr@0 333 error("pointNN out of range: 1 <= pointNN <= 1000");
mas01cr@0 334
mas01cr@0 335
mas01cr@0 336
mas01mc@18 337 trackNN=args_info.resultlength_arg;
mas01mc@18 338 if(trackNN<1 || trackNN >10000)
mas01cr@0 339 error("resultlength out of range: 1 <= resultlength <= 1000");
mas01cr@0 340
mas01cr@0 341
mas01cr@0 342 sequenceLength=args_info.sequencelength_arg;
mas01cr@0 343 if(sequenceLength<1 || sequenceLength >1000)
mas01cr@0 344 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01cr@0 345
mas01cr@0 346 sequenceHop=args_info.sequencehop_arg;
mas01cr@0 347 if(sequenceHop<1 || sequenceHop >1000)
mas01cr@0 348 error("seqhop out of range: 1 <= seqhop <= 1000");
mas01cr@0 349
mas01cr@0 350 return 0;
mas01cr@0 351 }
mas01cr@0 352 return -1; // no command found
mas01cr@0 353 }
mas01cr@0 354
mas01cr@0 355 /* Make a new database
mas01cr@0 356
mas01cr@0 357 The database consists of:
mas01cr@0 358
mas01cr@0 359 header
mas01cr@0 360 ---------------------------------------------------------------------------------
mas01cr@0 361 | magic 4 bytes| numFiles 4 bytes | dim 4 bytes | length 4 bytes |flags 4 bytes |
mas01cr@0 362 ---------------------------------------------------------------------------------
mas01cr@0 363
mas01cr@0 364
mas01mc@18 365 keyTable : list of keys of tracks
mas01cr@0 366 --------------------------------------------------------------------------
mas01cr@0 367 | key 256 bytes |
mas01cr@0 368 --------------------------------------------------------------------------
mas01cr@85 369 O2_MAXFILES*O2_FILENAMELENGTH
mas01cr@0 370
mas01mc@18 371 trackTable : Maps implicit feature index to a feature vector matrix
mas01cr@0 372 --------------------------------------------------------------------------
mas01cr@0 373 | numVectors (4 bytes) |
mas01cr@0 374 --------------------------------------------------------------------------
mas01cr@85 375 O2_MAXFILES * O2_MEANNUMFEATURES * sizeof(INT)
mas01cr@0 376
mas01cr@0 377 featureTable
mas01cr@0 378 --------------------------------------------------------------------------
mas01cr@0 379 | v1 v2 v3 ... vd (double) |
mas01cr@0 380 --------------------------------------------------------------------------
mas01cr@85 381 O2_MAXFILES * O2_MEANNUMFEATURES * DIM * sizeof(DOUBLE)
mas01cr@0 382
mas01cr@0 383 timesTable
mas01cr@0 384 --------------------------------------------------------------------------
mas01cr@0 385 | timestamp (double) |
mas01cr@0 386 --------------------------------------------------------------------------
mas01cr@85 387 O2_MAXFILES * O2_MEANNUMFEATURES * sizeof(DOUBLE)
mas01cr@0 388
mas01cr@0 389 l2normTable
mas01cr@0 390 --------------------------------------------------------------------------
mas01cr@0 391 | nm (double) |
mas01cr@0 392 --------------------------------------------------------------------------
mas01cr@85 393 O2_MAXFILES * O2_MEANNUMFEATURES * sizeof(DOUBLE)
mas01cr@0 394
mas01cr@0 395 */
mas01cr@0 396
mas01cr@30 397 void audioDB::get_lock(int fd, bool exclusive) {
mas01cr@30 398 struct flock lock;
mas01cr@30 399 int status;
mas01cr@30 400
mas01cr@30 401 lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
mas01cr@30 402 lock.l_whence = SEEK_SET;
mas01cr@30 403 lock.l_start = 0;
mas01cr@30 404 lock.l_len = 0; /* "the whole file" */
mas01cr@30 405
mas01cr@30 406 retry:
mas01cr@30 407 do {
mas01cr@30 408 status = fcntl(fd, F_SETLKW, &lock);
mas01cr@30 409 } while (status != 0 && errno == EINTR);
mas01cr@30 410
mas01cr@30 411 if (status) {
mas01cr@30 412 if (errno == EAGAIN) {
mas01cr@30 413 sleep(1);
mas01cr@30 414 goto retry;
mas01cr@30 415 } else {
mas01cr@32 416 error("fcntl lock error", "", "fcntl");
mas01cr@30 417 }
mas01cr@30 418 }
mas01cr@30 419 }
mas01cr@30 420
mas01cr@30 421 void audioDB::release_lock(int fd) {
mas01cr@30 422 struct flock lock;
mas01cr@30 423 int status;
mas01cr@30 424
mas01cr@30 425 lock.l_type = F_UNLCK;
mas01cr@30 426 lock.l_whence = SEEK_SET;
mas01cr@30 427 lock.l_start = 0;
mas01cr@30 428 lock.l_len = 0;
mas01cr@30 429
mas01cr@30 430 status = fcntl(fd, F_SETLKW, &lock);
mas01cr@30 431
mas01cr@30 432 if (status)
mas01cr@32 433 error("fcntl unlock error", "", "fcntl");
mas01cr@30 434 }
mas01cr@30 435
mas01cr@0 436 void audioDB::create(const char* dbName){
mas01cr@31 437 if ((dbfid = open (dbName, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
mas01cr@32 438 error("Can't create database file", dbName, "open");
mas01cr@30 439 get_lock(dbfid, 1);
mas01cr@0 440
mas01cr@0 441 // go to the location corresponding to the last byte
mas01cr@0 442 if (lseek (dbfid, O2_DEFAULTDBSIZE - 1, SEEK_SET) == -1)
mas01cr@32 443 error("lseek error in db file", "", "lseek");
mas01cr@0 444
mas01cr@0 445 // write a dummy byte at the last location
mas01cr@0 446 if (write (dbfid, "", 1) != 1)
mas01cr@32 447 error("write error", "", "write");
mas01cr@0 448
mas01cr@0 449 // mmap the output file
mas01cr@60 450 if(verbosity) {
mas01cr@0 451 cerr << "header size:" << O2_HEADERSIZE << endl;
mas01cr@60 452 }
mas01cr@0 453 if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | PROT_WRITE,
mas01cr@0 454 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
mas01cr@32 455 error("mmap error for creating database", "", "mmap");
mas01cr@0 456
mas01cr@0 457 dbH = new dbTableHeaderT();
mas01cr@0 458 assert(dbH);
mas01cr@0 459
mas01cr@0 460 // Initialize header
mas01cr@0 461 dbH->magic=O2_MAGIC;
mas01cr@0 462 dbH->numFiles=0;
mas01cr@0 463 dbH->length=0;
mas01cr@0 464 dbH->dim=0;
mas01cr@0 465 dbH->flags=0; //O2_FLAG_L2NORM;
mas01cr@0 466
mas01cr@0 467 memcpy (db, dbH, O2_HEADERSIZE);
mas01cr@60 468 if(verbosity) {
mas01cr@0 469 cerr << COM_CREATE << " " << dbName << endl;
mas01cr@60 470 }
mas01cr@0 471 }
mas01cr@0 472
mas01cr@0 473
mas01cr@0 474 void audioDB::drop(){
mas01cr@0 475
mas01cr@0 476
mas01cr@0 477 }
mas01cr@0 478
mas01cr@0 479 // initTables - memory map files passed as arguments
mas01cr@0 480 // Precondition: database has already been created
mas01cr@27 481 void audioDB::initTables(const char* dbName, bool forWrite, const char* inFile=0){
mas01cr@27 482 if ((dbfid = open (dbName, forWrite ? O_RDWR : O_RDONLY)) < 0)
mas01cr@32 483 error("Can't open database file", dbName, "open");
mas01cr@30 484 get_lock(dbfid, forWrite);
mas01cr@30 485
mas01cr@0 486 // open the input file
mas01cr@0 487 if (inFile && (infid = open (inFile, O_RDONLY)) < 0)
mas01cr@32 488 error("can't open input file for reading", inFile, "open");
mas01cr@0 489
mas01cr@0 490 // find size of input file
mas01cr@0 491 if (inFile && fstat (infid,&statbuf) < 0)
mas01cr@32 492 error("fstat error finding size of input", "", "fstat");
mas01cr@0 493
mas01cr@0 494 // Get the database header info
mas01cr@0 495 dbH = new dbTableHeaderT();
mas01cr@0 496 assert(dbH);
mas01cr@0 497
mas01cr@0 498 if(read(dbfid,(char*)dbH,sizeof(dbTableHeaderT))!=sizeof(dbTableHeaderT))
mas01cr@0 499 error("error reading db header");
mas01cr@0 500
mas01cr@0 501 fileTableOffset = O2_HEADERSIZE;
mas01mc@18 502 trackTableOffset = fileTableOffset + O2_FILETABLESIZE*O2_MAXFILES;
mas01mc@18 503 dataoffset = trackTableOffset + O2_TRACKTABLESIZE*O2_MAXFILES;
mas01cr@0 504 l2normTableOffset = O2_DEFAULTDBSIZE - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double);
mas01cr@0 505 timesTableOffset = l2normTableOffset - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double);
mas01cr@0 506
mas01cr@0 507 if(dbH->magic!=O2_MAGIC){
mas01cr@0 508 cerr << "expected: " << O2_MAGIC << ", got:" << dbH->magic << endl;
mas01cr@0 509 error("database file has incorrect header",dbName);
mas01cr@0 510 }
mas01cr@0 511
mas01cr@0 512 if(inFile)
mas01cr@0 513 if(dbH->dim==0 && dbH->length==0) // empty database
mas01cr@0 514 read(infid,&dbH->dim,sizeof(unsigned)); // initialize with input dimensionality
mas01cr@0 515 else {
mas01cr@0 516 unsigned test;
mas01cr@0 517 read(infid,&test,sizeof(unsigned));
mas01cr@0 518 if(dbH->dim!=test){
mas01cr@0 519 cerr << "error: expected dimension: " << dbH->dim << ", got :" << test <<endl;
mas01cr@0 520 error("feature dimensions do not match database table dimensions");
mas01cr@0 521 }
mas01cr@0 522 }
mas01cr@0 523
mas01cr@0 524 // mmap the input file
mas01cr@0 525 if (inFile && (indata = (char*)mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0))
mas01cr@0 526 == (caddr_t) -1)
mas01cr@32 527 error("mmap error for input", "", "mmap");
mas01cr@0 528
mas01cr@0 529 // mmap the database file
mas01cr@27 530 if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | (forWrite ? PROT_WRITE : 0),
mas01cr@0 531 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
mas01cr@32 532 error("mmap error for initting tables of database", "", "mmap");
mas01cr@0 533
mas01cr@0 534 // Make some handy tables with correct types
mas01cr@0 535 fileTable= (char*)(db+fileTableOffset);
mas01mc@18 536 trackTable = (unsigned*)(db+trackTableOffset);
mas01cr@0 537 dataBuf = (double*)(db+dataoffset);
mas01cr@0 538 l2normTable = (double*)(db+l2normTableOffset);
mas01cr@0 539 timesTable = (double*)(db+timesTableOffset);
mas01cr@0 540
mas01cr@0 541 }
mas01cr@0 542
mas01cr@0 543 void audioDB::insert(const char* dbName, const char* inFile){
mas01cr@0 544
mas01cr@27 545 initTables(dbName, 1, inFile);
mas01cr@0 546
mas01cr@0 547 if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 548 error("Must use timestamps with timestamped database","use --times");
mas01cr@0 549
mas01cr@0 550 // Check that there is room for at least 1 more file
mas01cr@0 551 if((char*)timesTable<((char*)dataBuf+dbH->length+statbuf.st_size-sizeof(int)))
mas01cr@0 552 error("No more room in database","insert failed: reason database is full.");
mas01cr@0 553
mas01cr@0 554 if(!key)
mas01cr@0 555 key=inFile;
mas01cr@0 556 // Linear scan of filenames check for pre-existing feature
mas01cr@0 557 unsigned alreadyInserted=0;
mas01cr@0 558 for(unsigned k=0; k<dbH->numFiles; k++)
mas01cr@0 559 if(strncmp(fileTable + k*O2_FILETABLESIZE, key, strlen(key))==0){
mas01cr@0 560 alreadyInserted=1;
mas01cr@0 561 break;
mas01cr@0 562 }
mas01cr@0 563
mas01cr@0 564 if(alreadyInserted){
mas01cr@60 565 if(verbosity) {
mas01cr@0 566 cerr << "Warning: key already exists in database, ignoring: " <<inFile << endl;
mas01cr@60 567 }
mas01cr@0 568 return;
mas01cr@0 569 }
mas01cr@0 570
mas01mc@18 571 // Make a track index table of features to file indexes
mas01cr@0 572 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 573 if(!numVectors){
mas01cr@60 574 if(verbosity) {
mas01cr@0 575 cerr << "Warning: ignoring zero-length feature vector file:" << key << endl;
mas01cr@60 576 }
mas01cr@0 577 // CLEAN UP
mas01cr@0 578 munmap(indata,statbuf.st_size);
mas01cr@0 579 munmap(db,O2_DEFAULTDBSIZE);
mas01cr@0 580 close(infid);
mas01cr@0 581 return;
mas01cr@0 582 }
mas01cr@0 583
mas01cr@0 584 strncpy(fileTable + dbH->numFiles*O2_FILETABLESIZE, key, strlen(key));
mas01cr@0 585
mas01cr@0 586 unsigned insertoffset = dbH->length;// Store current state
mas01cr@0 587
mas01cr@0 588 // Check times status and insert times from file
mas01cr@0 589 unsigned timesoffset=insertoffset/(dbH->dim*sizeof(double));
mas01cr@0 590 double* timesdata=timesTable+timesoffset;
mas01cr@0 591 assert(timesdata+numVectors<l2normTable);
mas01cr@0 592 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 593
mas01cr@0 594 // Increment file count
mas01cr@0 595 dbH->numFiles++;
mas01cr@0 596
mas01cr@0 597 // Update Header information
mas01cr@0 598 dbH->length+=(statbuf.st_size-sizeof(int));
mas01cr@0 599
mas01cr@0 600 // Copy the header back to the database
mas01cr@0 601 memcpy (db, dbH, sizeof(dbTableHeaderT));
mas01cr@0 602
mas01mc@18 603 // Update track to file index map
mas01mc@18 604 //memcpy (db+trackTableOffset+(dbH->numFiles-1)*sizeof(unsigned), &numVectors, sizeof(unsigned));
mas01mc@18 605 memcpy (trackTable+dbH->numFiles-1, &numVectors, sizeof(unsigned));
mas01cr@0 606
mas01cr@0 607 // Update the feature database
mas01cr@0 608 memcpy (db+dataoffset+insertoffset, indata+sizeof(int), statbuf.st_size-sizeof(int));
mas01cr@0 609
mas01cr@0 610 // Norm the vectors on input if the database is already L2 normed
mas01cr@0 611 if(dbH->flags & O2_FLAG_L2NORM)
mas01cr@0 612 unitNormAndInsertL2((double*)(db+dataoffset+insertoffset), dbH->dim, numVectors, 1); // append
mas01cr@0 613
mas01cr@0 614 // Report status
mas01cr@0 615 status(dbName);
mas01cr@60 616 if(verbosity) {
mas01cr@0 617 cerr << COM_INSERT << " " << dbName << " " << numVectors << " vectors "
mas01cr@0 618 << (statbuf.st_size-sizeof(int)) << " bytes." << endl;
mas01cr@60 619 }
mas01cr@0 620
mas01cr@0 621 // CLEAN UP
mas01cr@0 622 munmap(indata,statbuf.st_size);
mas01cr@0 623 close(infid);
mas01cr@0 624 }
mas01cr@0 625
mas01cr@0 626 void audioDB::insertTimeStamps(unsigned numVectors, ifstream* timesFile, double* timesdata){
mas01cr@0 627 unsigned numtimes=0;
mas01cr@0 628 if(usingTimes){
mas01cr@0 629 if(!(dbH->flags & O2_FLAG_TIMES) && !dbH->numFiles)
mas01cr@0 630 dbH->flags=dbH->flags|O2_FLAG_TIMES;
mas01cr@0 631 else if(!(dbH->flags&O2_FLAG_TIMES)){
mas01cr@0 632 cerr << "Warning: timestamp file used with non time-stamped database: ignoring timestamps" << endl;
mas01cr@0 633 usingTimes=0;
mas01cr@0 634 }
mas01cr@0 635
mas01cr@0 636 if(!timesFile->is_open()){
mas01cr@0 637 if(dbH->flags & O2_FLAG_TIMES){
mas01cr@0 638 munmap(indata,statbuf.st_size);
mas01cr@0 639 munmap(db,O2_DEFAULTDBSIZE);
mas01cr@0 640 error("problem opening times file on timestamped database",timesFileName);
mas01cr@0 641 }
mas01cr@0 642 else{
mas01cr@0 643 cerr << "Warning: problem opening times file. But non-timestamped database, so ignoring times file." << endl;
mas01cr@0 644 usingTimes=0;
mas01cr@0 645 }
mas01cr@0 646 }
mas01cr@0 647
mas01cr@0 648 // Process time file
mas01cr@0 649 if(usingTimes){
mas01cr@0 650 do{
mas01cr@0 651 *timesFile>>*timesdata++;
mas01cr@0 652 if(timesFile->eof())
mas01cr@0 653 break;
mas01cr@0 654 numtimes++;
mas01cr@0 655 }while(!timesFile->eof() && numtimes<numVectors);
mas01cr@0 656 if(!timesFile->eof()){
mas01cr@0 657 double dummy;
mas01cr@0 658 do{
mas01cr@0 659 *timesFile>>dummy;
mas01cr@0 660 if(timesFile->eof())
mas01cr@0 661 break;
mas01cr@0 662 numtimes++;
mas01cr@0 663 }while(!timesFile->eof());
mas01cr@0 664 }
mas01cr@0 665 if(numtimes<numVectors || numtimes>numVectors+2){
mas01cr@0 666 munmap(indata,statbuf.st_size);
mas01cr@0 667 munmap(db,O2_DEFAULTDBSIZE);
mas01cr@0 668 close(infid);
mas01cr@0 669 cerr << "expected " << numVectors << " found " << numtimes << endl;
mas01cr@0 670 error("Times file is incorrect length for features file",inFile);
mas01cr@0 671 }
mas01cr@60 672 if(verbosity>2) {
mas01cr@0 673 cerr << "numtimes: " << numtimes << endl;
mas01cr@60 674 }
mas01cr@0 675 }
mas01cr@0 676 }
mas01cr@0 677 }
mas01cr@0 678
mas01cr@0 679 void audioDB::batchinsert(const char* dbName, const char* inFile){
mas01cr@0 680
mas01cr@0 681 if ((dbfid = open (dbName, O_RDWR)) < 0)
mas01cr@32 682 error("Can't open database file", dbName, "open");
mas01cr@30 683 get_lock(dbfid, 1);
mas01cr@0 684
mas01cr@0 685 if(!key)
mas01cr@0 686 key=inFile;
mas01cr@0 687 ifstream *filesIn = 0;
mas01cr@0 688 ifstream *keysIn = 0;
mas01cr@0 689 ifstream* thisTimesFile = 0;
mas01cr@0 690
mas01cr@0 691 if(!(filesIn = new ifstream(inFile)))
mas01cr@0 692 error("Could not open batch in file", inFile);
mas01cr@0 693 if(key && key!=inFile)
mas01cr@0 694 if(!(keysIn = new ifstream(key)))
mas01cr@0 695 error("Could not open batch key file",key);
mas01cr@0 696
mas01cr@0 697 // Get the database header info
mas01cr@0 698 dbH = new dbTableHeaderT();
mas01cr@0 699 assert(dbH);
mas01cr@0 700
mas01cr@0 701 if(read(dbfid,(char*)dbH,sizeof(dbTableHeaderT))!=sizeof(dbTableHeaderT))
mas01cr@0 702 error("error reading db header");
mas01cr@0 703
mas01cr@0 704 if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 705 error("Must use timestamps with timestamped database","use --times");
mas01cr@0 706
mas01cr@0 707 fileTableOffset = O2_HEADERSIZE;
mas01mc@18 708 trackTableOffset = fileTableOffset + O2_FILETABLESIZE*O2_MAXFILES;
mas01mc@18 709 dataoffset = trackTableOffset + O2_TRACKTABLESIZE*O2_MAXFILES;
mas01cr@0 710 l2normTableOffset = O2_DEFAULTDBSIZE - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double);
mas01cr@0 711 timesTableOffset = l2normTableOffset - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double);
mas01cr@0 712
mas01cr@0 713 if(dbH->magic!=O2_MAGIC){
mas01cr@0 714 cerr << "expected:" << O2_MAGIC << ", got:" << dbH->magic << endl;
mas01cr@0 715 error("database file has incorrect header",dbName);
mas01cr@0 716 }
mas01cr@0 717
mas01cr@0 718
mas01cr@0 719 unsigned totalVectors=0;
mas01cr@0 720 char *thisKey = new char[MAXSTR];
mas01cr@0 721 char *thisFile = new char[MAXSTR];
mas01cr@0 722 char *thisTimesFileName = new char[MAXSTR];
mas01cr@0 723
mas01cr@0 724 do{
mas01cr@0 725 filesIn->getline(thisFile,MAXSTR);
mas01cr@0 726 if(key && key!=inFile)
mas01cr@0 727 keysIn->getline(thisKey,MAXSTR);
mas01cr@0 728 else
mas01cr@0 729 thisKey = thisFile;
mas01cr@0 730 if(usingTimes)
mas01cr@0 731 timesFile->getline(thisTimesFileName,MAXSTR);
mas01cr@0 732
mas01cr@0 733 if(filesIn->eof())
mas01cr@0 734 break;
mas01cr@0 735
mas01cr@0 736 // open the input file
mas01cr@0 737 if (thisFile && (infid = open (thisFile, O_RDONLY)) < 0)
mas01cr@32 738 error("can't open feature file for reading", thisFile, "open");
mas01cr@0 739
mas01cr@0 740 // find size of input file
mas01cr@0 741 if (thisFile && fstat (infid,&statbuf) < 0)
mas01cr@32 742 error("fstat error finding size of input", "", "fstat");
mas01cr@0 743
mas01mc@11 744 // mmap the database file
mas01mc@11 745 if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | PROT_WRITE,
mas01mc@11 746 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
mas01cr@32 747 error("mmap error for batchinsert into database", "", "mmap");
mas01mc@11 748
mas01mc@11 749 // Make some handy tables with correct types
mas01mc@11 750 fileTable= (char*)(db+fileTableOffset);
mas01mc@18 751 trackTable = (unsigned*)(db+trackTableOffset);
mas01mc@11 752 dataBuf = (double*)(db+dataoffset);
mas01mc@11 753 l2normTable = (double*)(db+l2normTableOffset);
mas01mc@11 754 timesTable = (double*)(db+timesTableOffset);
mas01mc@11 755
mas01cr@0 756 // Check that there is room for at least 1 more file
mas01cr@0 757 if((char*)timesTable<((char*)dataBuf+(dbH->length+statbuf.st_size-sizeof(int))))
mas01cr@0 758 error("No more room in database","insert failed: reason database is full.");
mas01cr@0 759
mas01cr@0 760 if(thisFile)
mas01cr@0 761 if(dbH->dim==0 && dbH->length==0) // empty database
mas01cr@0 762 read(infid,&dbH->dim,sizeof(unsigned)); // initialize with input dimensionality
mas01cr@0 763 else {
mas01cr@0 764 unsigned test;
mas01cr@0 765 read(infid,&test,sizeof(unsigned));
mas01cr@0 766 if(dbH->dim!=test){
mas01cr@0 767 cerr << "error: expected dimension: " << dbH->dim << ", got :" << test <<endl;
mas01cr@0 768 error("feature dimensions do not match database table dimensions");
mas01cr@0 769 }
mas01cr@0 770 }
mas01cr@0 771
mas01cr@0 772 // mmap the input file
mas01cr@0 773 if (thisFile && (indata = (char*)mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0))
mas01cr@0 774 == (caddr_t) -1)
mas01cr@32 775 error("mmap error for input", "", "mmap");
mas01cr@0 776
mas01cr@0 777
mas01cr@0 778 // Linear scan of filenames check for pre-existing feature
mas01cr@0 779 unsigned alreadyInserted=0;
mas01cr@0 780
mas01cr@0 781 for(unsigned k=0; k<dbH->numFiles; k++)
mas01cr@0 782 if(strncmp(fileTable + k*O2_FILETABLESIZE, thisKey, strlen(thisKey))==0){
mas01cr@0 783 alreadyInserted=1;
mas01cr@0 784 break;
mas01cr@0 785 }
mas01cr@0 786
mas01cr@0 787 if(alreadyInserted){
mas01cr@60 788 if(verbosity) {
mas01cr@0 789 cerr << "Warning: key already exists in database:" << thisKey << endl;
mas01cr@60 790 }
mas01cr@0 791 }
mas01cr@0 792 else{
mas01cr@0 793
mas01mc@18 794 // Make a track index table of features to file indexes
mas01cr@0 795 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 796 if(!numVectors){
mas01cr@60 797 if(verbosity) {
mas01cr@0 798 cerr << "Warning: ignoring zero-length feature vector file:" << thisKey << endl;
mas01cr@60 799 }
mas01cr@0 800 }
mas01cr@0 801 else{
mas01cr@0 802 if(usingTimes){
mas01cr@0 803 if(timesFile->eof())
mas01cr@0 804 error("not enough timestamp files in timesList");
mas01cr@0 805 thisTimesFile=new ifstream(thisTimesFileName,ios::in);
mas01cr@0 806 if(!thisTimesFile->is_open())
mas01cr@0 807 error("Cannot open timestamp file",thisTimesFileName);
mas01cr@0 808 unsigned insertoffset=dbH->length;
mas01cr@0 809 unsigned timesoffset=insertoffset/(dbH->dim*sizeof(double));
mas01cr@0 810 double* timesdata=timesTable+timesoffset;
mas01cr@0 811 assert(timesdata+numVectors<l2normTable);
mas01cr@0 812 insertTimeStamps(numVectors,thisTimesFile,timesdata);
mas01cr@0 813 if(thisTimesFile)
mas01cr@0 814 delete thisTimesFile;
mas01cr@0 815 }
mas01cr@0 816
mas01cr@0 817 strncpy(fileTable + dbH->numFiles*O2_FILETABLESIZE, thisKey, strlen(thisKey));
mas01cr@0 818
mas01cr@0 819 unsigned insertoffset = dbH->length;// Store current state
mas01cr@0 820
mas01cr@0 821 // Increment file count
mas01cr@0 822 dbH->numFiles++;
mas01cr@0 823
mas01cr@0 824 // Update Header information
mas01cr@0 825 dbH->length+=(statbuf.st_size-sizeof(int));
mas01cr@0 826 // Copy the header back to the database
mas01cr@0 827 memcpy (db, dbH, sizeof(dbTableHeaderT));
mas01cr@0 828
mas01mc@18 829 // Update track to file index map
mas01mc@18 830 //memcpy (db+trackTableOffset+(dbH->numFiles-1)*sizeof(unsigned), &numVectors, sizeof(unsigned));
mas01mc@18 831 memcpy (trackTable+dbH->numFiles-1, &numVectors, sizeof(unsigned));
mas01cr@0 832
mas01cr@0 833 // Update the feature database
mas01cr@0 834 memcpy (db+dataoffset+insertoffset, indata+sizeof(int), statbuf.st_size-sizeof(int));
mas01cr@0 835
mas01cr@0 836 // Norm the vectors on input if the database is already L2 normed
mas01cr@0 837 if(dbH->flags & O2_FLAG_L2NORM)
mas01cr@0 838 unitNormAndInsertL2((double*)(db+dataoffset+insertoffset), dbH->dim, numVectors, 1); // append
mas01cr@0 839
mas01cr@0 840 totalVectors+=numVectors;
mas01cr@0 841 }
mas01cr@0 842 }
mas01cr@0 843 // CLEAN UP
mas01cr@0 844 munmap(indata,statbuf.st_size);
mas01cr@0 845 close(infid);
mas01mc@11 846 munmap(db,O2_DEFAULTDBSIZE);
mas01cr@0 847 }while(!filesIn->eof());
mas01mc@12 848
mas01mc@12 849 // mmap the database file
mas01mc@12 850 if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | PROT_WRITE,
mas01mc@12 851 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
mas01cr@32 852 error("mmap error for creating database", "", "mmap");
mas01cr@0 853
mas01cr@60 854 if(verbosity) {
mas01cr@0 855 cerr << COM_BATCHINSERT << " " << dbName << " " << totalVectors << " vectors "
mas01cr@0 856 << totalVectors*dbH->dim*sizeof(double) << " bytes." << endl;
mas01cr@60 857 }
mas01cr@0 858
mas01cr@0 859 // Report status
mas01cr@0 860 status(dbName);
mas01mc@12 861
mas01mc@12 862 munmap(db,O2_DEFAULTDBSIZE);
mas01cr@0 863 }
mas01cr@0 864
mas01cr@76 865 // FIXME: this can't propagate the sequence length argument (used for
mas01cr@76 866 // dudCount). See adb__status() definition for the other half of
mas01cr@76 867 // this. -- CSR, 2007-10-01
mas01cr@0 868 void audioDB::ws_status(const char*dbName, char* hostport){
mas01cr@0 869 struct soap soap;
mas01cr@76 870 adb__statusResult adbStatusResult;
mas01cr@0 871
mas01cr@0 872 // Query an existing adb database
mas01cr@0 873 soap_init(&soap);
mas01cr@76 874 if(soap_call_adb__status(&soap,hostport,NULL,(char*)dbName,adbStatusResult)==SOAP_OK) {
mas01cr@76 875 cout << "numFiles = " << adbStatusResult.numFiles << endl;
mas01cr@76 876 cout << "dim = " << adbStatusResult.dim << endl;
mas01cr@76 877 cout << "length = " << adbStatusResult.length << endl;
mas01cr@76 878 cout << "dudCount = " << adbStatusResult.dudCount << endl;
mas01cr@76 879 cout << "nullCount = " << adbStatusResult.nullCount << endl;
mas01cr@76 880 cout << "flags = " << adbStatusResult.flags << endl;
mas01cr@76 881 } else {
mas01cr@0 882 soap_print_fault(&soap,stderr);
mas01cr@76 883 }
mas01cr@0 884
mas01cr@0 885 soap_destroy(&soap);
mas01cr@0 886 soap_end(&soap);
mas01cr@0 887 soap_done(&soap);
mas01cr@0 888 }
mas01cr@0 889
mas01mc@18 890 void audioDB::ws_query(const char*dbName, const char *trackKey, const char* hostport){
mas01cr@0 891 struct soap soap;
mas01cr@0 892 adb__queryResult adbQueryResult;
mas01cr@0 893
mas01cr@0 894 soap_init(&soap);
mas01cr@0 895 if(soap_call_adb__query(&soap,hostport,NULL,
mas01mc@18 896 (char*)dbName,(char*)trackKey,(char*)trackFileName,(char*)timesFileName,
mas01mc@18 897 queryType, queryPoint, pointNN, trackNN, sequenceLength, adbQueryResult)==SOAP_OK){
mas01cr@0 898 //std::cerr << "result list length:" << adbQueryResult.__sizeRlist << std::endl;
mas01cr@0 899 for(int i=0; i<adbQueryResult.__sizeRlist; i++)
mas01cr@0 900 std::cout << adbQueryResult.Rlist[i] << " " << adbQueryResult.Dist[i]
mas01cr@0 901 << " " << adbQueryResult.Qpos[i] << " " << adbQueryResult.Spos[i] << std::endl;
mas01cr@0 902 }
mas01cr@0 903 else
mas01cr@0 904 soap_print_fault(&soap,stderr);
mas01cr@0 905
mas01cr@0 906 soap_destroy(&soap);
mas01cr@0 907 soap_end(&soap);
mas01cr@0 908 soap_done(&soap);
mas01cr@0 909
mas01cr@0 910 }
mas01cr@0 911
mas01cr@0 912
mas01cr@76 913 void audioDB::status(const char* dbName, adb__statusResult *adbStatusResult){
mas01cr@0 914 if(!dbH)
mas01cr@27 915 initTables(dbName, 0, 0);
mas01cr@0 916
mas01cr@0 917 unsigned dudCount=0;
mas01cr@0 918 unsigned nullCount=0;
mas01cr@0 919 for(unsigned k=0; k<dbH->numFiles; k++){
mas01mc@18 920 if(trackTable[k]<sequenceLength){
mas01cr@0 921 dudCount++;
mas01mc@18 922 if(!trackTable[k])
mas01cr@76 923 nullCount++;
mas01cr@0 924 }
mas01cr@0 925 }
mas01cr@76 926
mas01cr@76 927 if(adbStatusResult == 0) {
mas01cr@76 928
mas01cr@76 929 // Update Header information
mas01cr@76 930 cout << "num files:" << dbH->numFiles << endl;
mas01cr@76 931 cout << "data dim:" << dbH->dim <<endl;
mas01cr@76 932 if(dbH->dim>0){
mas01cr@76 933 cout << "total vectors:" << dbH->length/(sizeof(double)*dbH->dim)<<endl;
mas01cr@76 934 cout << "vectors available:" << (timesTableOffset-(dataoffset+dbH->length))/(sizeof(double)*dbH->dim) << endl;
mas01cr@76 935 }
mas01cr@76 936 cout << "total bytes:" << dbH->length << " (" << (100.0*dbH->length)/(timesTableOffset-dataoffset) << "%)" << endl;
mas01cr@76 937 cout << "bytes available:" << timesTableOffset-(dataoffset+dbH->length) << " (" <<
mas01cr@76 938 (100.0*(timesTableOffset-(dataoffset+dbH->length)))/(timesTableOffset-dataoffset) << "%)" << endl;
mas01cr@76 939 cout << "flags:" << dbH->flags << endl;
mas01cr@76 940
mas01cr@76 941 cout << "null count: " << nullCount << " small sequence count " << dudCount-nullCount << endl;
mas01cr@76 942 } else {
mas01cr@76 943 adbStatusResult->numFiles = dbH->numFiles;
mas01cr@76 944 adbStatusResult->dim = dbH->dim;
mas01cr@76 945 adbStatusResult->length = dbH->length;
mas01cr@76 946 adbStatusResult->dudCount = dudCount;
mas01cr@76 947 adbStatusResult->nullCount = nullCount;
mas01cr@76 948 adbStatusResult->flags = dbH->flags;
mas01cr@76 949 }
mas01cr@0 950 }
mas01cr@0 951
mas01cr@0 952 void audioDB::dump(const char* dbName){
mas01cr@0 953 if(!dbH)
mas01cr@27 954 initTables(dbName, 0, 0);
mas01cr@0 955
mas01mc@17 956 for(unsigned k=0, j=0; k<dbH->numFiles; k++){
mas01mc@18 957 cout << fileTable+k*O2_FILETABLESIZE << " " << trackTable[k] << endl;
mas01mc@18 958 j+=trackTable[k];
mas01mc@17 959 }
mas01cr@0 960
mas01cr@0 961 status(dbName);
mas01cr@0 962 }
mas01cr@0 963
mas01cr@0 964 void audioDB::l2norm(const char* dbName){
mas01cr@50 965 initTables(dbName, true, 0);
mas01cr@0 966 if(dbH->length>0){
mas01cr@0 967 unsigned numVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01cr@0 968 unitNormAndInsertL2(dataBuf, dbH->dim, numVectors, 0); // No append
mas01cr@0 969 }
mas01cr@0 970 // Update database flags
mas01cr@0 971 dbH->flags = dbH->flags|O2_FLAG_L2NORM;
mas01cr@0 972 memcpy (db, dbH, O2_HEADERSIZE);
mas01cr@0 973 }
mas01cr@0 974
mas01cr@0 975
mas01cr@0 976
mas01cr@0 977 void audioDB::query(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){
mas01cr@0 978 switch(queryType){
mas01cr@0 979 case O2_FLAG_POINT_QUERY:
mas01cr@0 980 pointQuery(dbName, inFile, adbQueryResult);
mas01cr@0 981 break;
mas01cr@0 982 case O2_FLAG_SEQUENCE_QUERY:
mas01mc@17 983 if(radius==0)
mas01mc@20 984 trackSequenceQueryNN(dbName, inFile, adbQueryResult);
mas01mc@17 985 else
mas01mc@20 986 trackSequenceQueryRad(dbName, inFile, adbQueryResult);
mas01cr@0 987 break;
mas01mc@18 988 case O2_FLAG_TRACK_QUERY:
mas01mc@18 989 trackPointQuery(dbName, inFile, adbQueryResult);
mas01cr@0 990 break;
mas01cr@0 991 default:
mas01cr@0 992 error("unrecognized queryType in query()");
mas01cr@0 993
mas01cr@0 994 }
mas01cr@0 995 }
mas01cr@0 996
mas01cr@0 997 //return ordinal position of key in keyTable
mas01cr@0 998 unsigned audioDB::getKeyPos(char* key){
mas01cr@0 999 for(unsigned k=0; k<dbH->numFiles; k++)
mas01cr@0 1000 if(strncmp(fileTable + k*O2_FILETABLESIZE, key, strlen(key))==0)
mas01cr@0 1001 return k;
mas01cr@0 1002 error("Key not found",key);
mas01cr@0 1003 return O2_ERR_KEYNOTFOUND;
mas01cr@0 1004 }
mas01cr@0 1005
mas01cr@0 1006 // Basic point query engine
mas01cr@0 1007 void audioDB::pointQuery(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){
mas01cr@0 1008
mas01cr@27 1009 initTables(dbName, 0, inFile);
mas01cr@0 1010
mas01cr@0 1011 // For each input vector, find the closest pointNN matching output vectors and report
mas01cr@0 1012 // we use stdout in this stub version
mas01cr@0 1013 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 1014
mas01cr@0 1015 double* query = (double*)(indata+sizeof(int));
mas01cr@0 1016 double* data = dataBuf;
mas01cr@0 1017 double* queryCopy = 0;
mas01cr@0 1018
mas01cr@0 1019 if( dbH->flags & O2_FLAG_L2NORM ){
mas01cr@0 1020 // Make a copy of the query
mas01cr@0 1021 queryCopy = new double[numVectors*dbH->dim];
mas01cr@0 1022 qNorm = new double[numVectors];
mas01cr@0 1023 assert(queryCopy&&qNorm);
mas01cr@0 1024 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01cr@0 1025 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01cr@0 1026 query = queryCopy;
mas01cr@0 1027 }
mas01cr@0 1028
mas01cr@0 1029 // Make temporary dynamic memory for results
mas01cr@0 1030 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01cr@0 1031 double distances[pointNN];
mas01cr@0 1032 unsigned qIndexes[pointNN];
mas01cr@0 1033 unsigned sIndexes[pointNN];
mas01cr@0 1034 for(unsigned k=0; k<pointNN; k++){
mas01cr@62 1035 distances[k]=-DBL_MAX;
mas01cr@0 1036 qIndexes[k]=~0;
mas01cr@0 1037 sIndexes[k]=~0;
mas01cr@0 1038 }
mas01cr@0 1039
mas01cr@0 1040 unsigned j=numVectors;
mas01cr@0 1041 unsigned k,l,n;
mas01cr@0 1042 double thisDist;
mas01cr@0 1043
mas01cr@0 1044 unsigned totalVecs=dbH->length/(dbH->dim*sizeof(double));
mas01cr@0 1045 double meanQdur = 0;
mas01cr@0 1046 double* timesdata = 0;
mas01cr@0 1047 double* dbdurs = 0;
mas01cr@0 1048
mas01cr@0 1049 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1050 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01cr@0 1051 usingTimes=0;
mas01cr@0 1052 }
mas01cr@0 1053
mas01cr@0 1054 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 1055 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01cr@0 1056
mas01cr@0 1057 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1058 timesdata = new double[numVectors];
mas01cr@0 1059 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 1060 // Calculate durations of points
mas01cr@0 1061 for(k=0; k<numVectors-1; k++){
mas01cr@0 1062 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01cr@0 1063 meanQdur+=timesdata[k];
mas01cr@0 1064 }
mas01cr@0 1065 meanQdur/=k;
mas01cr@0 1066 // Individual exhaustive timepoint durations
mas01cr@0 1067 dbdurs = new double[totalVecs];
mas01cr@0 1068 for(k=0; k<totalVecs-1; k++)
mas01cr@0 1069 dbdurs[k]=timesTable[k+1]-timesTable[k];
mas01cr@0 1070 j--; // decrement vector counter by one
mas01cr@0 1071 }
mas01cr@0 1072
mas01cr@0 1073 if(usingQueryPoint)
mas01cr@0 1074 if(queryPoint>numVectors-1)
mas01cr@0 1075 error("queryPoint > numVectors in query");
mas01cr@0 1076 else{
mas01cr@60 1077 if(verbosity>1) {
mas01cr@0 1078 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 1079 }
mas01cr@0 1080 query=query+queryPoint*dbH->dim;
mas01cr@0 1081 numVectors=queryPoint+1;
mas01cr@0 1082 j=1;
mas01cr@0 1083 }
mas01cr@0 1084
mas01cr@0 1085 gettimeofday(&tv1, NULL);
mas01cr@0 1086 while(j--){ // query
mas01cr@0 1087 data=dataBuf;
mas01cr@0 1088 k=totalVecs; // number of database vectors
mas01cr@0 1089 while(k--){ // database
mas01cr@0 1090 thisDist=0;
mas01cr@0 1091 l=dbH->dim;
mas01cr@0 1092 double* q=query;
mas01cr@0 1093 while(l--)
mas01cr@0 1094 thisDist+=*q++**data++;
mas01cr@0 1095 if(!usingTimes ||
mas01cr@0 1096 (usingTimes
mas01cr@0 1097 && fabs(dbdurs[totalVecs-k-1]-timesdata[numVectors-j-1])<timesdata[numVectors-j-1]*timesTol)){
mas01cr@0 1098 n=pointNN;
mas01cr@0 1099 while(n--){
mas01cr@0 1100 if(thisDist>=distances[n]){
mas01cr@0 1101 if((n==0 || thisDist<=distances[n-1])){
mas01cr@0 1102 // Copy all values above up the queue
mas01cr@0 1103 for( l=pointNN-1 ; l >= n+1 ; l--){
mas01cr@0 1104 distances[l]=distances[l-1];
mas01cr@0 1105 qIndexes[l]=qIndexes[l-1];
mas01cr@0 1106 sIndexes[l]=sIndexes[l-1];
mas01cr@0 1107 }
mas01cr@0 1108 distances[n]=thisDist;
mas01cr@0 1109 qIndexes[n]=numVectors-j-1;
mas01cr@0 1110 sIndexes[n]=dbH->length/(sizeof(double)*dbH->dim)-k-1;
mas01cr@0 1111 break;
mas01cr@0 1112 }
mas01cr@0 1113 }
mas01cr@0 1114 else
mas01cr@0 1115 break;
mas01cr@0 1116 }
mas01cr@0 1117 }
mas01cr@0 1118 }
mas01cr@0 1119 // Move query pointer to next query point
mas01cr@0 1120 query+=dbH->dim;
mas01cr@0 1121 }
mas01cr@0 1122
mas01cr@0 1123 gettimeofday(&tv2, NULL);
mas01cr@60 1124 if(verbosity>1) {
mas01cr@0 1125 cerr << endl << " elapsed time:" << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01cr@60 1126 }
mas01cr@0 1127
mas01cr@0 1128 if(adbQueryResult==0){
mas01cr@0 1129 // Output answer
mas01cr@0 1130 // Loop over nearest neighbours
mas01cr@0 1131 for(k=0; k < pointNN; k++){
mas01cr@0 1132 // Scan for key
mas01mc@18 1133 unsigned cumTrack=0;
mas01cr@0 1134 for(l=0 ; l<dbH->numFiles; l++){
mas01mc@18 1135 cumTrack+=trackTable[l];
mas01mc@18 1136 if(sIndexes[k]<cumTrack){
mas01cr@0 1137 cout << fileTable+l*O2_FILETABLESIZE << " " << distances[k] << " " << qIndexes[k] << " "
mas01mc@18 1138 << sIndexes[k]+trackTable[l]-cumTrack << endl;
mas01cr@0 1139 break;
mas01cr@0 1140 }
mas01cr@0 1141 }
mas01cr@0 1142 }
mas01cr@0 1143 }
mas01cr@0 1144 else{ // Process Web Services Query
mas01cr@89 1145 int listLen;
mas01cr@89 1146 for(k = 0; k < pointNN; k++) {
mas01cr@89 1147 if(distances[k] == -DBL_MAX)
mas01cr@89 1148 break;
mas01cr@89 1149 }
mas01cr@89 1150 listLen = k;
mas01cr@89 1151
mas01cr@0 1152 adbQueryResult->__sizeRlist=listLen;
mas01cr@0 1153 adbQueryResult->__sizeDist=listLen;
mas01cr@0 1154 adbQueryResult->__sizeQpos=listLen;
mas01cr@0 1155 adbQueryResult->__sizeSpos=listLen;
mas01cr@0 1156 adbQueryResult->Rlist= new char*[listLen];
mas01cr@0 1157 adbQueryResult->Dist = new double[listLen];
mas01cr@86 1158 adbQueryResult->Qpos = new unsigned int[listLen];
mas01cr@86 1159 adbQueryResult->Spos = new unsigned int[listLen];
mas01cr@59 1160 for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){
mas01cr@0 1161 adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR];
mas01cr@0 1162 adbQueryResult->Dist[k]=distances[k];
mas01cr@0 1163 adbQueryResult->Qpos[k]=qIndexes[k];
mas01mc@18 1164 unsigned cumTrack=0;
mas01cr@0 1165 for(l=0 ; l<dbH->numFiles; l++){
mas01mc@18 1166 cumTrack+=trackTable[l];
mas01mc@18 1167 if(sIndexes[k]<cumTrack){
mas01cr@0 1168 sprintf(adbQueryResult->Rlist[k], "%s", fileTable+l*O2_FILETABLESIZE);
mas01cr@0 1169 break;
mas01cr@0 1170 }
mas01cr@0 1171 }
mas01mc@18 1172 adbQueryResult->Spos[k]=sIndexes[k]+trackTable[l]-cumTrack;
mas01cr@0 1173 }
mas01cr@0 1174 }
mas01cr@0 1175
mas01cr@0 1176 // Clean up
mas01cr@0 1177 if(queryCopy)
mas01cr@0 1178 delete queryCopy;
mas01cr@0 1179 if(qNorm)
mas01cr@0 1180 delete qNorm;
mas01cr@0 1181 if(timesdata)
mas01cr@0 1182 delete timesdata;
mas01cr@0 1183 if(dbdurs)
mas01cr@0 1184 delete dbdurs;
mas01cr@0 1185 }
mas01cr@0 1186
mas01mc@18 1187 // trackPointQuery
mas01mc@18 1188 // return the trackNN closest tracks to the query track
mas01mc@18 1189 // uses average of pointNN points per track
mas01mc@18 1190 void audioDB::trackPointQuery(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){
mas01cr@27 1191 initTables(dbName, 0, inFile);
mas01cr@0 1192
mas01cr@0 1193 // For each input vector, find the closest pointNN matching output vectors and report
mas01cr@0 1194 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 1195 double* query = (double*)(indata+sizeof(int));
mas01cr@0 1196 double* data = dataBuf;
mas01cr@0 1197 double* queryCopy = 0;
mas01cr@0 1198
mas01cr@0 1199 if( dbH->flags & O2_FLAG_L2NORM ){
mas01cr@0 1200 // Make a copy of the query
mas01cr@0 1201 queryCopy = new double[numVectors*dbH->dim];
mas01cr@0 1202 qNorm = new double[numVectors];
mas01cr@0 1203 assert(queryCopy&&qNorm);
mas01cr@0 1204 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01cr@0 1205 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01cr@0 1206 query = queryCopy;
mas01cr@0 1207 }
mas01cr@0 1208
mas01cr@0 1209 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01mc@18 1210 assert(trackNN>0 && trackNN<=O2_MAXNN);
mas01cr@0 1211
mas01cr@0 1212 // Make temporary dynamic memory for results
mas01mc@18 1213 double trackDistances[trackNN];
mas01mc@18 1214 unsigned trackIDs[trackNN];
mas01mc@18 1215 unsigned trackQIndexes[trackNN];
mas01mc@18 1216 unsigned trackSIndexes[trackNN];
mas01cr@0 1217
mas01cr@0 1218 double distances[pointNN];
mas01cr@0 1219 unsigned qIndexes[pointNN];
mas01cr@0 1220 unsigned sIndexes[pointNN];
mas01cr@0 1221
mas01cr@0 1222 unsigned j=numVectors; // number of query points
mas01mc@18 1223 unsigned k,l,n, track, trackOffset=0, processedTracks=0;
mas01cr@0 1224 double thisDist;
mas01cr@0 1225
mas01cr@0 1226 for(k=0; k<pointNN; k++){
mas01cr@66 1227 distances[k]=-DBL_MAX;
mas01cr@0 1228 qIndexes[k]=~0;
mas01cr@0 1229 sIndexes[k]=~0;
mas01cr@0 1230 }
mas01cr@0 1231
mas01mc@18 1232 for(k=0; k<trackNN; k++){
mas01cr@66 1233 trackDistances[k]=-DBL_MAX;
mas01mc@18 1234 trackQIndexes[k]=~0;
mas01mc@18 1235 trackSIndexes[k]=~0;
mas01mc@18 1236 trackIDs[k]=~0;
mas01cr@0 1237 }
mas01cr@0 1238
mas01cr@0 1239 double meanQdur = 0;
mas01cr@0 1240 double* timesdata = 0;
mas01cr@0 1241 double* meanDBdur = 0;
mas01cr@0 1242
mas01cr@0 1243 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1244 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01cr@0 1245 usingTimes=0;
mas01cr@0 1246 }
mas01cr@0 1247
mas01cr@0 1248 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 1249 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01cr@0 1250
mas01cr@0 1251 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1252 timesdata = new double[numVectors];
mas01cr@0 1253 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 1254 // Calculate durations of points
mas01cr@0 1255 for(k=0; k<numVectors-1; k++){
mas01cr@0 1256 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01cr@0 1257 meanQdur+=timesdata[k];
mas01cr@0 1258 }
mas01cr@0 1259 meanQdur/=k;
mas01cr@0 1260 meanDBdur = new double[dbH->numFiles];
mas01cr@0 1261 for(k=0; k<dbH->numFiles; k++){
mas01cr@0 1262 meanDBdur[k]=0.0;
mas01mc@18 1263 for(j=0; j<trackTable[k]-1 ; j++)
mas01cr@0 1264 meanDBdur[k]+=timesTable[j+1]-timesTable[j];
mas01cr@0 1265 meanDBdur[k]/=j;
mas01cr@0 1266 }
mas01cr@0 1267 }
mas01cr@0 1268
mas01cr@0 1269 if(usingQueryPoint)
mas01cr@0 1270 if(queryPoint>numVectors-1)
mas01cr@0 1271 error("queryPoint > numVectors in query");
mas01cr@0 1272 else{
mas01cr@60 1273 if(verbosity>1) {
mas01cr@0 1274 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 1275 }
mas01cr@0 1276 query=query+queryPoint*dbH->dim;
mas01cr@0 1277 numVectors=queryPoint+1;
mas01cr@0 1278 }
mas01cr@0 1279
mas01mc@18 1280 // build track offset table
mas01mc@18 1281 unsigned *trackOffsetTable = new unsigned[dbH->numFiles];
mas01mc@18 1282 unsigned cumTrack=0;
mas01mc@18 1283 unsigned trackIndexOffset;
mas01cr@0 1284 for(k=0; k<dbH->numFiles;k++){
mas01mc@18 1285 trackOffsetTable[k]=cumTrack;
mas01mc@18 1286 cumTrack+=trackTable[k]*dbH->dim;
mas01cr@0 1287 }
mas01cr@0 1288
mas01cr@0 1289 char nextKey[MAXSTR];
mas01cr@0 1290
mas01cr@0 1291 gettimeofday(&tv1, NULL);
mas01cr@0 1292
mas01mc@18 1293 for(processedTracks=0, track=0 ; processedTracks < dbH->numFiles ; track++, processedTracks++){
mas01mc@18 1294 if(trackFile){
mas01mc@18 1295 if(!trackFile->eof()){
mas01mc@18 1296 trackFile->getline(nextKey,MAXSTR);
mas01mc@18 1297 track=getKeyPos(nextKey);
mas01cr@0 1298 }
mas01cr@0 1299 else
mas01cr@0 1300 break;
mas01cr@0 1301 }
mas01mc@18 1302 trackOffset=trackOffsetTable[track]; // numDoubles offset
mas01mc@18 1303 trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
mas01cr@60 1304 if(verbosity>7) {
mas01mc@18 1305 cerr << track << "." << trackOffset/(dbH->dim) << "." << trackTable[track] << " | ";cerr.flush();
mas01cr@60 1306 }
mas01cr@0 1307
mas01cr@0 1308 if(dbH->flags & O2_FLAG_L2NORM)
mas01cr@0 1309 usingQueryPoint?query=queryCopy+queryPoint*dbH->dim:query=queryCopy;
mas01cr@0 1310 else
mas01cr@0 1311 usingQueryPoint?query=(double*)(indata+sizeof(int))+queryPoint*dbH->dim:query=(double*)(indata+sizeof(int));
mas01cr@0 1312 if(usingQueryPoint)
mas01cr@0 1313 j=1;
mas01cr@0 1314 else
mas01cr@0 1315 j=numVectors;
mas01cr@0 1316 while(j--){
mas01mc@18 1317 k=trackTable[track]; // number of vectors in track
mas01mc@18 1318 data=dataBuf+trackOffset; // data for track
mas01cr@0 1319 while(k--){
mas01cr@0 1320 thisDist=0;
mas01cr@0 1321 l=dbH->dim;
mas01cr@0 1322 double* q=query;
mas01cr@0 1323 while(l--)
mas01cr@0 1324 thisDist+=*q++**data++;
mas01cr@0 1325 if(!usingTimes ||
mas01cr@0 1326 (usingTimes
mas01mc@18 1327 && fabs(meanDBdur[track]-meanQdur)<meanQdur*timesTol)){
mas01cr@0 1328 n=pointNN;
mas01cr@0 1329 while(n--){
mas01cr@0 1330 if(thisDist>=distances[n]){
mas01cr@0 1331 if((n==0 || thisDist<=distances[n-1])){
mas01cr@0 1332 // Copy all values above up the queue
mas01cr@0 1333 for( l=pointNN-1 ; l > n ; l--){
mas01cr@0 1334 distances[l]=distances[l-1];
mas01cr@0 1335 qIndexes[l]=qIndexes[l-1];
mas01cr@0 1336 sIndexes[l]=sIndexes[l-1];
mas01cr@0 1337 }
mas01cr@0 1338 distances[n]=thisDist;
mas01cr@0 1339 qIndexes[n]=numVectors-j-1;
mas01mc@18 1340 sIndexes[n]=trackTable[track]-k-1;
mas01cr@0 1341 break;
mas01cr@0 1342 }
mas01cr@0 1343 }
mas01cr@0 1344 else
mas01cr@0 1345 break;
mas01cr@0 1346 }
mas01cr@0 1347 }
mas01mc@18 1348 } // track
mas01cr@0 1349 // Move query pointer to next query point
mas01cr@0 1350 query+=dbH->dim;
mas01cr@0 1351 } // query
mas01mc@18 1352 // Take the average of this track's distance
mas01mc@18 1353 // Test the track distances
mas01cr@0 1354 thisDist=0;
mas01cr@66 1355 for (n = 0; n < pointNN; n++) {
mas01cr@66 1356 if (distances[n] == -DBL_MAX) break;
mas01cr@66 1357 thisDist += distances[n];
mas01cr@66 1358 }
mas01cr@66 1359 thisDist /= n;
mas01cr@66 1360
mas01mc@18 1361 n=trackNN;
mas01cr@0 1362 while(n--){
mas01mc@18 1363 if(thisDist>=trackDistances[n]){
mas01mc@18 1364 if((n==0 || thisDist<=trackDistances[n-1])){
mas01cr@0 1365 // Copy all values above up the queue
mas01cr@74 1366 for( l=trackNN-1 ; l > n ; l--){
mas01mc@18 1367 trackDistances[l]=trackDistances[l-1];
mas01mc@18 1368 trackQIndexes[l]=trackQIndexes[l-1];
mas01mc@18 1369 trackSIndexes[l]=trackSIndexes[l-1];
mas01mc@18 1370 trackIDs[l]=trackIDs[l-1];
mas01cr@0 1371 }
mas01mc@18 1372 trackDistances[n]=thisDist;
mas01mc@18 1373 trackQIndexes[n]=qIndexes[0];
mas01mc@18 1374 trackSIndexes[n]=sIndexes[0];
mas01mc@18 1375 trackIDs[n]=track;
mas01cr@0 1376 break;
mas01cr@0 1377 }
mas01cr@0 1378 }
mas01cr@0 1379 else
mas01cr@0 1380 break;
mas01cr@0 1381 }
mas01cr@0 1382 for(unsigned k=0; k<pointNN; k++){
mas01cr@66 1383 distances[k]=-DBL_MAX;
mas01cr@0 1384 qIndexes[k]=~0;
mas01cr@0 1385 sIndexes[k]=~0;
mas01cr@0 1386 }
mas01mc@18 1387 } // tracks
mas01cr@0 1388 gettimeofday(&tv2, NULL);
mas01cr@0 1389
mas01cr@60 1390 if(verbosity>1) {
mas01mc@18 1391 cerr << endl << "processed tracks :" << processedTracks
mas01cr@0 1392 << " elapsed time:" << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01cr@60 1393 }
mas01cr@0 1394
mas01cr@0 1395 if(adbQueryResult==0){
mas01cr@60 1396 if(verbosity>1) {
mas01cr@0 1397 cerr<<endl;
mas01cr@60 1398 }
mas01cr@0 1399 // Output answer
mas01cr@0 1400 // Loop over nearest neighbours
mas01mc@18 1401 for(k=0; k < min(trackNN,processedTracks); k++)
mas01mc@18 1402 cout << fileTable+trackIDs[k]*O2_FILETABLESIZE
mas01mc@18 1403 << " " << trackDistances[k] << " " << trackQIndexes[k] << " " << trackSIndexes[k] << endl;
mas01cr@0 1404 }
mas01cr@0 1405 else{ // Process Web Services Query
mas01mc@18 1406 int listLen = min(trackNN, processedTracks);
mas01cr@0 1407 adbQueryResult->__sizeRlist=listLen;
mas01cr@0 1408 adbQueryResult->__sizeDist=listLen;
mas01cr@0 1409 adbQueryResult->__sizeQpos=listLen;
mas01cr@0 1410 adbQueryResult->__sizeSpos=listLen;
mas01cr@0 1411 adbQueryResult->Rlist= new char*[listLen];
mas01cr@0 1412 adbQueryResult->Dist = new double[listLen];
mas01cr@86 1413 adbQueryResult->Qpos = new unsigned int[listLen];
mas01cr@86 1414 adbQueryResult->Spos = new unsigned int[listLen];
mas01cr@59 1415 for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){
mas01cr@0 1416 adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR];
mas01mc@18 1417 adbQueryResult->Dist[k]=trackDistances[k];
mas01mc@18 1418 adbQueryResult->Qpos[k]=trackQIndexes[k];
mas01mc@18 1419 adbQueryResult->Spos[k]=trackSIndexes[k];
mas01mc@18 1420 sprintf(adbQueryResult->Rlist[k], "%s", fileTable+trackIDs[k]*O2_FILETABLESIZE);
mas01cr@0 1421 }
mas01cr@0 1422 }
mas01cr@0 1423
mas01cr@0 1424
mas01cr@0 1425 // Clean up
mas01mc@18 1426 if(trackOffsetTable)
mas01mc@18 1427 delete trackOffsetTable;
mas01cr@0 1428 if(queryCopy)
mas01cr@0 1429 delete queryCopy;
mas01cr@0 1430 if(qNorm)
mas01cr@0 1431 delete qNorm;
mas01cr@0 1432 if(timesdata)
mas01cr@0 1433 delete timesdata;
mas01cr@0 1434 if(meanDBdur)
mas01cr@0 1435 delete meanDBdur;
mas01cr@0 1436
mas01cr@0 1437 }
mas01cr@0 1438
mas01cr@0 1439
mas01mc@20 1440 // k nearest-neighbor (k-NN) search between query and target tracks
mas01mc@20 1441 // efficient implementation based on matched filter
mas01mc@20 1442 // assumes normed shingles
mas01mc@20 1443 // outputs distances of retrieved shingles, max retreived = pointNN shingles per per track
mas01mc@20 1444 void audioDB::trackSequenceQueryNN(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){
mas01cr@0 1445
mas01cr@27 1446 initTables(dbName, 0, inFile);
mas01cr@0 1447
mas01cr@0 1448 // For each input vector, find the closest pointNN matching output vectors and report
mas01cr@0 1449 // we use stdout in this stub version
mas01cr@0 1450 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 1451 double* query = (double*)(indata+sizeof(int));
mas01cr@0 1452 double* queryCopy = 0;
mas01cr@0 1453
mas01cr@0 1454 double qMeanL2;
mas01cr@0 1455 double* sMeanL2;
mas01cr@0 1456
mas01cr@0 1457 unsigned USE_THRESH=0;
mas01cr@0 1458 double SILENCE_THRESH=0;
mas01cr@0 1459 double DIFF_THRESH=0;
mas01cr@0 1460
mas01cr@0 1461 if(!(dbH->flags & O2_FLAG_L2NORM) )
mas01cr@55 1462 error("Database must be L2 normed for sequence query","use -L2NORM");
mas01cr@55 1463
mas01cr@55 1464 if(numVectors<sequenceLength)
mas01cr@55 1465 error("Query shorter than requested sequence length", "maybe use -l");
mas01cr@0 1466
mas01cr@60 1467 if(verbosity>1) {
mas01cr@0 1468 cerr << "performing norms ... "; cerr.flush();
mas01cr@60 1469 }
mas01cr@0 1470 unsigned dbVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01mc@20 1471
mas01cr@0 1472 // Make a copy of the query
mas01cr@0 1473 queryCopy = new double[numVectors*dbH->dim];
mas01cr@0 1474 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01cr@0 1475 qNorm = new double[numVectors];
mas01cr@0 1476 sNorm = new double[dbVectors];
mas01cr@0 1477 sMeanL2=new double[dbH->numFiles];
mas01cr@0 1478 assert(qNorm&&sNorm&&queryCopy&&sMeanL2&&sequenceLength);
mas01cr@0 1479 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01cr@0 1480 query = queryCopy;
mas01mc@20 1481
mas01cr@0 1482 // Make norm measurements relative to sequenceLength
mas01cr@0 1483 unsigned w = sequenceLength-1;
mas01cr@0 1484 unsigned i,j;
mas01cr@0 1485 double* ps;
mas01cr@0 1486 double tmp1,tmp2;
mas01mc@20 1487
mas01cr@0 1488 // Copy the L2 norm values to core to avoid disk random access later on
mas01cr@0 1489 memcpy(sNorm, l2normTable, dbVectors*sizeof(double));
mas01cr@0 1490 double* snPtr = sNorm;
mas01cr@0 1491 for(i=0; i<dbH->numFiles; i++){
mas01mc@20 1492 if(trackTable[i]>=sequenceLength){
mas01cr@0 1493 tmp1=*snPtr;
mas01cr@0 1494 j=1;
mas01cr@0 1495 w=sequenceLength-1;
mas01cr@0 1496 while(w--)
mas01cr@0 1497 *snPtr+=snPtr[j++];
mas01cr@0 1498 ps = snPtr+1;
mas01mc@18 1499 w=trackTable[i]-sequenceLength; // +1 - 1
mas01cr@0 1500 while(w--){
mas01cr@0 1501 tmp2=*ps;
mas01mc@20 1502 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01cr@0 1503 tmp1=tmp2;
mas01cr@0 1504 ps++;
mas01cr@0 1505 }
mas01mc@20 1506 ps = snPtr;
mas01mc@20 1507 w=trackTable[i]-sequenceLength+1;
mas01mc@20 1508 while(w--){
mas01mc@20 1509 *ps=sqrt(*ps);
mas01mc@20 1510 ps++;
mas01mc@20 1511 }
mas01cr@0 1512 }
mas01mc@18 1513 snPtr+=trackTable[i];
mas01cr@0 1514 }
mas01cr@0 1515
mas01cr@0 1516 double* pn = sMeanL2;
mas01cr@0 1517 w=dbH->numFiles;
mas01cr@0 1518 while(w--)
mas01cr@0 1519 *pn++=0.0;
mas01cr@0 1520 ps=sNorm;
mas01mc@18 1521 unsigned processedTracks=0;
mas01cr@0 1522 for(i=0; i<dbH->numFiles; i++){
mas01mc@18 1523 if(trackTable[i]>sequenceLength-1){
mas01cr@57 1524 w = trackTable[i]-sequenceLength+1;
mas01cr@0 1525 pn = sMeanL2+i;
mas01mc@20 1526 *pn=0;
mas01cr@0 1527 while(w--)
mas01mc@20 1528 if(*ps>0)
mas01mc@20 1529 *pn+=*ps++;
mas01cr@57 1530 *pn/=trackTable[i]-sequenceLength+1;
mas01cr@0 1531 SILENCE_THRESH+=*pn;
mas01mc@18 1532 processedTracks++;
mas01cr@0 1533 }
mas01mc@18 1534 ps = sNorm + trackTable[i];
mas01cr@0 1535 }
mas01cr@60 1536 if(verbosity>1) {
mas01mc@18 1537 cerr << "processedTracks: " << processedTracks << endl;
mas01cr@60 1538 }
mas01mc@20 1539
mas01mc@18 1540 SILENCE_THRESH/=processedTracks;
mas01cr@0 1541 USE_THRESH=1; // Turn thresholding on
mas01mc@20 1542 DIFF_THRESH=SILENCE_THRESH; // mean shingle power
mas01mc@20 1543 SILENCE_THRESH/=5; // 20% of the mean shingle power is SILENCE
mas01cr@60 1544 if(verbosity>4) {
mas01mc@20 1545 cerr << "silence thresh: " << SILENCE_THRESH;
mas01cr@60 1546 }
mas01cr@0 1547 w=sequenceLength-1;
mas01cr@0 1548 i=1;
mas01cr@0 1549 tmp1=*qNorm;
mas01cr@0 1550 while(w--)
mas01cr@0 1551 *qNorm+=qNorm[i++];
mas01cr@0 1552 ps = qNorm+1;
mas01mc@20 1553 w=numVectors-sequenceLength; // +1 -1
mas01cr@0 1554 while(w--){
mas01cr@0 1555 tmp2=*ps;
mas01mc@20 1556 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01cr@0 1557 tmp1=tmp2;
mas01mc@20 1558 ps++;
mas01mc@20 1559 }
mas01mc@20 1560 ps = qNorm;
mas01mc@20 1561 qMeanL2 = 0;
mas01mc@20 1562 w=numVectors-sequenceLength+1;
mas01mc@20 1563 while(w--){
mas01mc@20 1564 *ps=sqrt(*ps);
mas01mc@20 1565 qMeanL2+=*ps++;
mas01cr@0 1566 }
mas01cr@0 1567 qMeanL2 /= numVectors-sequenceLength+1;
mas01mc@20 1568
mas01cr@60 1569 if(verbosity>1) {
mas01cr@60 1570 cerr << "done." << endl;
mas01cr@60 1571 }
mas01cr@0 1572
mas01cr@60 1573 if(verbosity>1) {
mas01mc@18 1574 cerr << "matching tracks..." << endl;
mas01cr@60 1575 }
mas01cr@0 1576
mas01cr@0 1577 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01mc@18 1578 assert(trackNN>0 && trackNN<=O2_MAXNN);
mas01cr@0 1579
mas01cr@0 1580 // Make temporary dynamic memory for results
mas01mc@18 1581 double trackDistances[trackNN];
mas01mc@18 1582 unsigned trackIDs[trackNN];
mas01mc@18 1583 unsigned trackQIndexes[trackNN];
mas01mc@18 1584 unsigned trackSIndexes[trackNN];
mas01cr@0 1585
mas01cr@0 1586 double distances[pointNN];
mas01cr@0 1587 unsigned qIndexes[pointNN];
mas01cr@0 1588 unsigned sIndexes[pointNN];
mas01cr@0 1589
mas01cr@0 1590
mas01mc@18 1591 unsigned k,l,m,n,track,trackOffset=0, HOP_SIZE=sequenceHop, wL=sequenceLength;
mas01cr@0 1592 double thisDist;
mas01cr@0 1593
mas01cr@0 1594 for(k=0; k<pointNN; k++){
mas01mc@20 1595 distances[k]=1.0e6;
mas01cr@0 1596 qIndexes[k]=~0;
mas01cr@0 1597 sIndexes[k]=~0;
mas01cr@0 1598 }
mas01cr@0 1599
mas01mc@18 1600 for(k=0; k<trackNN; k++){
mas01mc@20 1601 trackDistances[k]=1.0e6;
mas01mc@18 1602 trackQIndexes[k]=~0;
mas01mc@18 1603 trackSIndexes[k]=~0;
mas01mc@18 1604 trackIDs[k]=~0;
mas01cr@0 1605 }
mas01cr@0 1606
mas01cr@0 1607 // Timestamp and durations processing
mas01cr@0 1608 double meanQdur = 0;
mas01cr@0 1609 double* timesdata = 0;
mas01cr@0 1610 double* meanDBdur = 0;
mas01cr@0 1611
mas01cr@0 1612 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1613 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01cr@0 1614 usingTimes=0;
mas01cr@0 1615 }
mas01cr@0 1616
mas01cr@0 1617 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 1618 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01cr@0 1619
mas01cr@0 1620 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1621 timesdata = new double[numVectors];
mas01cr@0 1622 assert(timesdata);
mas01cr@0 1623 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 1624 // Calculate durations of points
mas01cr@0 1625 for(k=0; k<numVectors-1; k++){
mas01cr@0 1626 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01cr@0 1627 meanQdur+=timesdata[k];
mas01cr@0 1628 }
mas01cr@0 1629 meanQdur/=k;
mas01cr@60 1630 if(verbosity>1) {
mas01cr@0 1631 cerr << "mean query file duration: " << meanQdur << endl;
mas01cr@60 1632 }
mas01cr@0 1633 meanDBdur = new double[dbH->numFiles];
mas01cr@0 1634 assert(meanDBdur);
mas01cr@0 1635 for(k=0; k<dbH->numFiles; k++){
mas01cr@0 1636 meanDBdur[k]=0.0;
mas01mc@18 1637 for(j=0; j<trackTable[k]-1 ; j++)
mas01cr@0 1638 meanDBdur[k]+=timesTable[j+1]-timesTable[j];
mas01cr@0 1639 meanDBdur[k]/=j;
mas01cr@0 1640 }
mas01cr@0 1641 }
mas01cr@0 1642
mas01cr@0 1643 if(usingQueryPoint)
mas01cr@0 1644 if(queryPoint>numVectors || queryPoint>numVectors-wL+1)
mas01cr@0 1645 error("queryPoint > numVectors-wL+1 in query");
mas01cr@0 1646 else{
mas01cr@60 1647 if(verbosity>1) {
mas01cr@0 1648 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 1649 }
mas01cr@0 1650 query=query+queryPoint*dbH->dim;
mas01cr@0 1651 qNorm=qNorm+queryPoint;
mas01cr@0 1652 numVectors=wL;
mas01cr@0 1653 }
mas01cr@0 1654
mas01mc@20 1655 double ** D = 0; // Differences query and target
mas01cr@0 1656 double ** DD = 0; // Matched filter distance
mas01cr@0 1657
mas01cr@0 1658 D = new double*[numVectors];
mas01cr@0 1659 assert(D);
mas01cr@0 1660 DD = new double*[numVectors];
mas01cr@0 1661 assert(DD);
mas01cr@0 1662
mas01cr@0 1663 gettimeofday(&tv1, NULL);
mas01mc@18 1664 processedTracks=0;
mas01mc@18 1665 unsigned successfulTracks=0;
mas01cr@0 1666
mas01cr@0 1667 double* qp;
mas01cr@0 1668 double* sp;
mas01cr@0 1669 double* dp;
mas01cr@0 1670
mas01mc@18 1671 // build track offset table
mas01mc@18 1672 unsigned *trackOffsetTable = new unsigned[dbH->numFiles];
mas01mc@18 1673 unsigned cumTrack=0;
mas01mc@18 1674 unsigned trackIndexOffset;
mas01cr@0 1675 for(k=0; k<dbH->numFiles;k++){
mas01mc@18 1676 trackOffsetTable[k]=cumTrack;
mas01mc@18 1677 cumTrack+=trackTable[k]*dbH->dim;
mas01cr@0 1678 }
mas01cr@0 1679
mas01cr@0 1680 char nextKey [MAXSTR];
mas01mc@20 1681
mas01mc@20 1682 // chi^2 statistics
mas01mc@20 1683 double sampleCount = 0;
mas01mc@20 1684 double sampleSum = 0;
mas01mc@20 1685 double logSampleSum = 0;
mas01mc@20 1686 double minSample = 1e9;
mas01mc@20 1687 double maxSample = 0;
mas01mc@20 1688
mas01mc@20 1689 // Track loop
mas01mc@18 1690 for(processedTracks=0, track=0 ; processedTracks < dbH->numFiles ; track++, processedTracks++){
mas01cr@0 1691
mas01mc@18 1692 // get trackID from file if using a control file
mas01mc@18 1693 if(trackFile){
mas01mc@18 1694 if(!trackFile->eof()){
mas01mc@18 1695 trackFile->getline(nextKey,MAXSTR);
mas01mc@18 1696 track=getKeyPos(nextKey);
mas01cr@0 1697 }
mas01cr@0 1698 else
mas01cr@0 1699 break;
mas01cr@0 1700 }
mas01mc@12 1701
mas01mc@18 1702 trackOffset=trackOffsetTable[track]; // numDoubles offset
mas01mc@18 1703 trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
mas01cr@0 1704
mas01cr@57 1705 if(sequenceLength<=trackTable[track]){ // test for short sequences
mas01cr@0 1706
mas01cr@60 1707 if(verbosity>7) {
mas01mc@18 1708 cerr << track << "." << trackIndexOffset << "." << trackTable[track] << " | ";cerr.flush();
mas01cr@60 1709 }
mas01cr@0 1710
mas01mc@20 1711 // Sum products matrix
mas01cr@0 1712 for(j=0; j<numVectors;j++){
mas01mc@18 1713 D[j]=new double[trackTable[track]];
mas01cr@0 1714 assert(D[j]);
mas01cr@0 1715
mas01cr@0 1716 }
mas01cr@0 1717
mas01cr@0 1718 // Matched filter matrix
mas01cr@0 1719 for(j=0; j<numVectors;j++){
mas01mc@18 1720 DD[j]=new double[trackTable[track]];
mas01cr@0 1721 assert(DD[j]);
mas01cr@0 1722 }
mas01cr@0 1723
mas01mc@20 1724 // Dot product
mas01cr@0 1725 for(j=0; j<numVectors; j++)
mas01mc@18 1726 for(k=0; k<trackTable[track]; k++){
mas01cr@0 1727 qp=query+j*dbH->dim;
mas01mc@18 1728 sp=dataBuf+trackOffset+k*dbH->dim;
mas01cr@0 1729 DD[j][k]=0.0; // Initialize matched filter array
mas01cr@0 1730 dp=&D[j][k]; // point to correlation cell j,k
mas01cr@0 1731 *dp=0.0; // initialize correlation cell
mas01cr@0 1732 l=dbH->dim; // size of vectors
mas01cr@0 1733 while(l--)
mas01cr@0 1734 *dp+=*qp++**sp++;
mas01cr@0 1735 }
mas01cr@0 1736
mas01cr@0 1737 // Matched Filter
mas01cr@0 1738 // HOP SIZE == 1
mas01cr@0 1739 double* spd;
mas01cr@0 1740 if(HOP_SIZE==1){ // HOP_SIZE = shingleHop
mas01cr@0 1741 for(w=0; w<wL; w++)
mas01cr@0 1742 for(j=0; j<numVectors-w; j++){
mas01cr@0 1743 sp=DD[j];
mas01cr@0 1744 spd=D[j+w]+w;
mas01mc@18 1745 k=trackTable[track]-w;
mas01cr@0 1746 while(k--)
mas01cr@0 1747 *sp+++=*spd++;
mas01cr@0 1748 }
mas01cr@0 1749 }
mas01mc@20 1750
mas01cr@0 1751 else{ // HOP_SIZE != 1
mas01cr@0 1752 for(w=0; w<wL; w++)
mas01cr@0 1753 for(j=0; j<numVectors-w; j+=HOP_SIZE){
mas01cr@0 1754 sp=DD[j];
mas01cr@0 1755 spd=D[j+w]+w;
mas01mc@18 1756 for(k=0; k<trackTable[track]-w; k+=HOP_SIZE){
mas01cr@0 1757 *sp+=*spd;
mas01cr@0 1758 sp+=HOP_SIZE;
mas01cr@0 1759 spd+=HOP_SIZE;
mas01cr@0 1760 }
mas01cr@0 1761 }
mas01cr@0 1762 }
mas01cr@0 1763
mas01cr@60 1764 if(verbosity>3 && usingTimes) {
mas01mc@18 1765 cerr << "meanQdur=" << meanQdur << " meanDBdur=" << meanDBdur[track] << endl;
mas01cr@0 1766 cerr.flush();
mas01cr@0 1767 }
mas01cr@0 1768
mas01cr@0 1769 if(!usingTimes ||
mas01cr@0 1770 (usingTimes
mas01mc@18 1771 && fabs(meanDBdur[track]-meanQdur)<meanQdur*timesTol)){
mas01cr@0 1772
mas01cr@60 1773 if(verbosity>3 && usingTimes) {
mas01cr@0 1774 cerr << "within duration tolerance." << endl;
mas01cr@0 1775 cerr.flush();
mas01cr@0 1776 }
mas01cr@0 1777
mas01cr@0 1778 // Search for minimum distance by shingles (concatenated vectors)
mas01cr@53 1779 for(j=0;j<=numVectors-wL;j+=HOP_SIZE)
mas01cr@53 1780 for(k=0;k<=trackTable[track]-wL;k+=HOP_SIZE){
mas01mc@20 1781 thisDist=2-(2/(qNorm[j]*sNorm[trackIndexOffset+k]))*DD[j][k];
mas01cr@60 1782 if(verbosity>10) {
mas01mc@20 1783 cerr << thisDist << " " << qNorm[j] << " " << sNorm[trackIndexOffset+k] << endl;
mas01cr@60 1784 }
mas01mc@20 1785 // Gather chi^2 statistics
mas01mc@20 1786 if(thisDist<minSample)
mas01mc@20 1787 minSample=thisDist;
mas01mc@20 1788 else if(thisDist>maxSample)
mas01mc@20 1789 maxSample=thisDist;
mas01mc@20 1790 if(thisDist>1e-9){
mas01mc@20 1791 sampleCount++;
mas01mc@20 1792 sampleSum+=thisDist;
mas01mc@20 1793 logSampleSum+=log(thisDist);
mas01mc@20 1794 }
mas01mc@20 1795
mas01mc@20 1796 // diffL2 = fabs(qNorm[j] - sNorm[trackIndexOffset+k]);
mas01cr@0 1797 // Power test
mas01cr@0 1798 if(!USE_THRESH ||
mas01cr@0 1799 // Threshold on mean L2 of Q and S sequences
mas01mc@20 1800 (USE_THRESH && qNorm[j]>SILENCE_THRESH && sNorm[trackIndexOffset+k]>SILENCE_THRESH &&
mas01cr@0 1801 // Are both query and target windows above mean energy?
mas01mc@20 1802 (qNorm[j]>qMeanL2*.25 && sNorm[trackIndexOffset+k]>sMeanL2[track]*.25))) // && diffL2 < DIFF_THRESH )))
mas01mc@20 1803 thisDist=thisDist; // Computed above
mas01cr@0 1804 else
mas01mc@20 1805 thisDist=1000000.0;
mas01mc@20 1806
mas01mc@20 1807 // k-NN match algorithm
mas01cr@58 1808 m=pointNN;
mas01mc@20 1809 while(m--){
mas01mc@20 1810 if(thisDist<=distances[m])
mas01mc@20 1811 if(m==0 || thisDist>=distances[m-1]){
mas01cr@0 1812 // Shuffle distances up the list
mas01cr@0 1813 for(l=pointNN-1; l>m; l--){
mas01cr@0 1814 distances[l]=distances[l-1];
mas01cr@0 1815 qIndexes[l]=qIndexes[l-1];
mas01cr@0 1816 sIndexes[l]=sIndexes[l-1];
mas01cr@0 1817 }
mas01cr@0 1818 distances[m]=thisDist;
mas01cr@0 1819 if(usingQueryPoint)
mas01cr@0 1820 qIndexes[m]=queryPoint;
mas01cr@0 1821 else
mas01cr@0 1822 qIndexes[m]=j;
mas01cr@0 1823 sIndexes[m]=k;
mas01cr@0 1824 break;
mas01mc@20 1825 }
mas01cr@0 1826 }
mas01cr@0 1827 }
mas01cr@0 1828 // Calculate the mean of the N-Best matches
mas01cr@0 1829 thisDist=0.0;
mas01cr@53 1830 for(m=0; m<pointNN; m++) {
mas01cr@53 1831 if (distances[m] == 1000000.0) break;
mas01mc@20 1832 thisDist+=distances[m];
mas01cr@53 1833 }
mas01cr@53 1834 thisDist/=m;
mas01cr@0 1835
mas01mc@12 1836 // Let's see the distances then...
mas01cr@60 1837 if(verbosity>3) {
mas01mc@18 1838 cerr << fileTable+track*O2_FILETABLESIZE << " " << thisDist << endl;
mas01cr@60 1839 }
mas01mc@12 1840
mas01mc@20 1841
mas01mc@18 1842 // All the track stuff goes here
mas01cr@58 1843 n=trackNN;
mas01cr@0 1844 while(n--){
mas01mc@20 1845 if(thisDist<=trackDistances[n]){
mas01mc@20 1846 if((n==0 || thisDist>=trackDistances[n-1])){
mas01cr@0 1847 // Copy all values above up the queue
mas01mc@18 1848 for( l=trackNN-1 ; l > n ; l--){
mas01mc@18 1849 trackDistances[l]=trackDistances[l-1];
mas01mc@18 1850 trackQIndexes[l]=trackQIndexes[l-1];
mas01mc@18 1851 trackSIndexes[l]=trackSIndexes[l-1];
mas01mc@18 1852 trackIDs[l]=trackIDs[l-1];
mas01cr@0 1853 }
mas01mc@18 1854 trackDistances[n]=thisDist;
mas01mc@18 1855 trackQIndexes[n]=qIndexes[0];
mas01mc@18 1856 trackSIndexes[n]=sIndexes[0];
mas01mc@18 1857 successfulTracks++;
mas01mc@18 1858 trackIDs[n]=track;
mas01cr@0 1859 break;
mas01cr@0 1860 }
mas01cr@0 1861 }
mas01cr@0 1862 else
mas01cr@0 1863 break;
mas01cr@0 1864 }
mas01cr@0 1865 } // Duration match
mas01mc@20 1866
mas01mc@18 1867 // Clean up current track
mas01cr@0 1868 if(D!=NULL){
mas01cr@0 1869 for(j=0; j<numVectors; j++)
mas01cr@0 1870 delete[] D[j];
mas01cr@0 1871 }
mas01cr@0 1872
mas01cr@0 1873 if(DD!=NULL){
mas01cr@0 1874 for(j=0; j<numVectors; j++)
mas01cr@0 1875 delete[] DD[j];
mas01cr@0 1876 }
mas01cr@0 1877 }
mas01mc@20 1878 // per-track reset array values
mas01mc@20 1879 for(unsigned k=0; k<pointNN; k++){
mas01mc@20 1880 distances[k]=1.0e6;
mas01mc@20 1881 qIndexes[k]=~0;
mas01mc@20 1882 sIndexes[k]=~0;
mas01mc@20 1883 }
mas01cr@0 1884 }
mas01cr@0 1885
mas01cr@0 1886 gettimeofday(&tv2,NULL);
mas01cr@60 1887 if(verbosity>1) {
mas01mc@18 1888 cerr << endl << "processed tracks :" << processedTracks << " matched tracks: " << successfulTracks << " elapsed time:"
mas01cr@0 1889 << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01mc@20 1890 cerr << "sampleCount: " << sampleCount << " sampleSum: " << sampleSum << " logSampleSum: " << logSampleSum
mas01mc@20 1891 << " minSample: " << minSample << " maxSample: " << maxSample << endl;
mas01mc@20 1892 }
mas01cr@0 1893 if(adbQueryResult==0){
mas01cr@60 1894 if(verbosity>1) {
mas01cr@0 1895 cerr<<endl;
mas01cr@60 1896 }
mas01cr@0 1897 // Output answer
mas01cr@0 1898 // Loop over nearest neighbours
mas01mc@18 1899 for(k=0; k < min(trackNN,successfulTracks); k++)
mas01mc@20 1900 cout << fileTable+trackIDs[k]*O2_FILETABLESIZE << " " << trackDistances[k] << " "
mas01mc@20 1901 << trackQIndexes[k] << " " << trackSIndexes[k] << endl;
mas01cr@0 1902 }
mas01cr@0 1903 else{ // Process Web Services Query
mas01mc@18 1904 int listLen = min(trackNN, processedTracks);
mas01cr@0 1905 adbQueryResult->__sizeRlist=listLen;
mas01cr@0 1906 adbQueryResult->__sizeDist=listLen;
mas01cr@0 1907 adbQueryResult->__sizeQpos=listLen;
mas01cr@0 1908 adbQueryResult->__sizeSpos=listLen;
mas01cr@0 1909 adbQueryResult->Rlist= new char*[listLen];
mas01cr@0 1910 adbQueryResult->Dist = new double[listLen];
mas01cr@86 1911 adbQueryResult->Qpos = new unsigned int[listLen];
mas01cr@86 1912 adbQueryResult->Spos = new unsigned int[listLen];
mas01cr@59 1913 for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){
mas01cr@0 1914 adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR];
mas01mc@18 1915 adbQueryResult->Dist[k]=trackDistances[k];
mas01mc@18 1916 adbQueryResult->Qpos[k]=trackQIndexes[k];
mas01mc@18 1917 adbQueryResult->Spos[k]=trackSIndexes[k];
mas01mc@18 1918 sprintf(adbQueryResult->Rlist[k], "%s", fileTable+trackIDs[k]*O2_FILETABLESIZE);
mas01cr@0 1919 }
mas01cr@0 1920 }
mas01cr@0 1921
mas01cr@0 1922
mas01cr@0 1923 // Clean up
mas01mc@18 1924 if(trackOffsetTable)
mas01mc@20 1925 delete[] trackOffsetTable;
mas01cr@0 1926 if(queryCopy)
mas01mc@20 1927 delete[] queryCopy;
mas01cr@0 1928 //if(qNorm)
mas01cr@0 1929 //delete qNorm;
mas01cr@0 1930 if(D)
mas01cr@0 1931 delete[] D;
mas01cr@0 1932 if(DD)
mas01cr@0 1933 delete[] DD;
mas01cr@0 1934 if(timesdata)
mas01mc@20 1935 delete[] timesdata;
mas01cr@0 1936 if(meanDBdur)
mas01mc@20 1937 delete[] meanDBdur;
mas01cr@0 1938
mas01cr@0 1939
mas01cr@0 1940 }
mas01cr@0 1941
mas01mc@20 1942 // Radius search between query and target tracks
mas01mc@20 1943 // efficient implementation based on matched filter
mas01mc@20 1944 // assumes normed shingles
mas01mc@20 1945 // outputs count of retrieved shingles, max retreived = one shingle per query shingle per track
mas01mc@20 1946 void audioDB::trackSequenceQueryRad(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){
mas01mc@17 1947
mas01cr@27 1948 initTables(dbName, 0, inFile);
mas01mc@17 1949
mas01mc@17 1950 // For each input vector, find the closest pointNN matching output vectors and report
mas01mc@17 1951 // we use stdout in this stub version
mas01mc@17 1952 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01mc@17 1953 double* query = (double*)(indata+sizeof(int));
mas01mc@17 1954 double* queryCopy = 0;
mas01mc@17 1955
mas01mc@17 1956 double qMeanL2;
mas01mc@17 1957 double* sMeanL2;
mas01mc@17 1958
mas01mc@17 1959 unsigned USE_THRESH=0;
mas01mc@17 1960 double SILENCE_THRESH=0;
mas01mc@17 1961 double DIFF_THRESH=0;
mas01mc@17 1962
mas01mc@17 1963 if(!(dbH->flags & O2_FLAG_L2NORM) )
mas01mc@17 1964 error("Database must be L2 normed for sequence query","use -l2norm");
mas01mc@17 1965
mas01cr@60 1966 if(verbosity>1) {
mas01mc@17 1967 cerr << "performing norms ... "; cerr.flush();
mas01cr@60 1968 }
mas01mc@17 1969 unsigned dbVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01mc@18 1970
mas01mc@17 1971 // Make a copy of the query
mas01mc@17 1972 queryCopy = new double[numVectors*dbH->dim];
mas01mc@17 1973 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01mc@17 1974 qNorm = new double[numVectors];
mas01mc@17 1975 sNorm = new double[dbVectors];
mas01mc@17 1976 sMeanL2=new double[dbH->numFiles];
mas01mc@17 1977 assert(qNorm&&sNorm&&queryCopy&&sMeanL2&&sequenceLength);
mas01mc@17 1978 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01mc@17 1979 query = queryCopy;
mas01mc@18 1980
mas01mc@17 1981 // Make norm measurements relative to sequenceLength
mas01mc@17 1982 unsigned w = sequenceLength-1;
mas01mc@17 1983 unsigned i,j;
mas01mc@17 1984 double* ps;
mas01mc@17 1985 double tmp1,tmp2;
mas01mc@18 1986
mas01mc@17 1987 // Copy the L2 norm values to core to avoid disk random access later on
mas01mc@17 1988 memcpy(sNorm, l2normTable, dbVectors*sizeof(double));
mas01mc@17 1989 double* snPtr = sNorm;
mas01mc@17 1990 for(i=0; i<dbH->numFiles; i++){
mas01mc@18 1991 if(trackTable[i]>=sequenceLength){
mas01mc@17 1992 tmp1=*snPtr;
mas01mc@17 1993 j=1;
mas01mc@17 1994 w=sequenceLength-1;
mas01mc@17 1995 while(w--)
mas01mc@17 1996 *snPtr+=snPtr[j++];
mas01mc@17 1997 ps = snPtr+1;
mas01mc@18 1998 w=trackTable[i]-sequenceLength; // +1 - 1
mas01mc@17 1999 while(w--){
mas01mc@17 2000 tmp2=*ps;
mas01mc@17 2001 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01mc@17 2002 tmp1=tmp2;
mas01mc@17 2003 ps++;
mas01mc@17 2004 }
mas01mc@17 2005 ps = snPtr;
mas01mc@18 2006 w=trackTable[i]-sequenceLength+1;
mas01mc@17 2007 while(w--){
mas01mc@17 2008 *ps=sqrt(*ps);
mas01mc@17 2009 ps++;
mas01mc@17 2010 }
mas01mc@17 2011 }
mas01mc@18 2012 snPtr+=trackTable[i];
mas01mc@17 2013 }
mas01mc@17 2014
mas01mc@17 2015 double* pn = sMeanL2;
mas01mc@17 2016 w=dbH->numFiles;
mas01mc@17 2017 while(w--)
mas01mc@17 2018 *pn++=0.0;
mas01mc@17 2019 ps=sNorm;
mas01mc@18 2020 unsigned processedTracks=0;
mas01mc@17 2021 for(i=0; i<dbH->numFiles; i++){
mas01mc@18 2022 if(trackTable[i]>sequenceLength-1){
mas01cr@70 2023 w = trackTable[i]-sequenceLength+1;
mas01mc@17 2024 pn = sMeanL2+i;
mas01mc@17 2025 *pn=0;
mas01mc@17 2026 while(w--)
mas01mc@17 2027 if(*ps>0)
mas01mc@17 2028 *pn+=*ps++;
mas01cr@70 2029 *pn/=trackTable[i]-sequenceLength+1;
mas01mc@17 2030 SILENCE_THRESH+=*pn;
mas01mc@18 2031 processedTracks++;
mas01mc@17 2032 }
mas01mc@18 2033 ps = sNorm + trackTable[i];
mas01mc@17 2034 }
mas01cr@60 2035 if(verbosity>1) {
mas01mc@18 2036 cerr << "processedTracks: " << processedTracks << endl;
mas01cr@60 2037 }
mas01mc@17 2038
mas01mc@18 2039 SILENCE_THRESH/=processedTracks;
mas01mc@17 2040 USE_THRESH=1; // Turn thresholding on
mas01mc@18 2041 DIFF_THRESH=SILENCE_THRESH; // mean shingle power
mas01mc@17 2042 SILENCE_THRESH/=5; // 20% of the mean shingle power is SILENCE
mas01cr@60 2043 if(verbosity>4) {
mas01mc@17 2044 cerr << "silence thresh: " << SILENCE_THRESH;
mas01cr@60 2045 }
mas01mc@17 2046 w=sequenceLength-1;
mas01mc@17 2047 i=1;
mas01mc@17 2048 tmp1=*qNorm;
mas01mc@17 2049 while(w--)
mas01mc@17 2050 *qNorm+=qNorm[i++];
mas01mc@17 2051 ps = qNorm+1;
mas01mc@17 2052 w=numVectors-sequenceLength; // +1 -1
mas01mc@17 2053 while(w--){
mas01mc@17 2054 tmp2=*ps;
mas01mc@17 2055 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01mc@17 2056 tmp1=tmp2;
mas01mc@17 2057 ps++;
mas01mc@17 2058 }
mas01mc@17 2059 ps = qNorm;
mas01mc@17 2060 qMeanL2 = 0;
mas01mc@17 2061 w=numVectors-sequenceLength+1;
mas01mc@17 2062 while(w--){
mas01mc@17 2063 *ps=sqrt(*ps);
mas01mc@17 2064 qMeanL2+=*ps++;
mas01mc@17 2065 }
mas01mc@17 2066 qMeanL2 /= numVectors-sequenceLength+1;
mas01mc@17 2067
mas01cr@60 2068 if(verbosity>1) {
mas01mc@17 2069 cerr << "done." << endl;
mas01cr@60 2070 }
mas01mc@17 2071
mas01cr@60 2072 if(verbosity>1) {
mas01mc@18 2073 cerr << "matching tracks..." << endl;
mas01cr@60 2074 }
mas01mc@17 2075
mas01mc@17 2076 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01mc@18 2077 assert(trackNN>0 && trackNN<=O2_MAXNN);
mas01mc@17 2078
mas01mc@17 2079 // Make temporary dynamic memory for results
mas01mc@18 2080 double trackDistances[trackNN];
mas01mc@18 2081 unsigned trackIDs[trackNN];
mas01mc@18 2082 unsigned trackQIndexes[trackNN];
mas01mc@18 2083 unsigned trackSIndexes[trackNN];
mas01mc@17 2084
mas01mc@17 2085 double distances[pointNN];
mas01mc@17 2086 unsigned qIndexes[pointNN];
mas01mc@17 2087 unsigned sIndexes[pointNN];
mas01mc@17 2088
mas01mc@17 2089
mas01cr@59 2090 unsigned k,l,n,track,trackOffset=0, HOP_SIZE=sequenceHop, wL=sequenceLength;
mas01mc@17 2091 double thisDist;
mas01mc@17 2092
mas01mc@17 2093 for(k=0; k<pointNN; k++){
mas01mc@17 2094 distances[k]=0.0;
mas01mc@17 2095 qIndexes[k]=~0;
mas01mc@17 2096 sIndexes[k]=~0;
mas01mc@17 2097 }
mas01mc@17 2098
mas01mc@18 2099 for(k=0; k<trackNN; k++){
mas01mc@18 2100 trackDistances[k]=0.0;
mas01mc@18 2101 trackQIndexes[k]=~0;
mas01mc@18 2102 trackSIndexes[k]=~0;
mas01mc@18 2103 trackIDs[k]=~0;
mas01mc@17 2104 }
mas01mc@17 2105
mas01mc@17 2106 // Timestamp and durations processing
mas01mc@17 2107 double meanQdur = 0;
mas01mc@17 2108 double* timesdata = 0;
mas01mc@17 2109 double* meanDBdur = 0;
mas01mc@17 2110
mas01mc@17 2111 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01mc@17 2112 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01mc@17 2113 usingTimes=0;
mas01mc@17 2114 }
mas01mc@17 2115
mas01mc@17 2116 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01mc@17 2117 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01mc@17 2118
mas01mc@17 2119 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01mc@17 2120 timesdata = new double[numVectors];
mas01mc@17 2121 assert(timesdata);
mas01mc@17 2122 insertTimeStamps(numVectors, timesFile, timesdata);
mas01mc@17 2123 // Calculate durations of points
mas01mc@17 2124 for(k=0; k<numVectors-1; k++){
mas01mc@17 2125 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01mc@17 2126 meanQdur+=timesdata[k];
mas01mc@17 2127 }
mas01mc@17 2128 meanQdur/=k;
mas01cr@60 2129 if(verbosity>1) {
mas01mc@17 2130 cerr << "mean query file duration: " << meanQdur << endl;
mas01cr@60 2131 }
mas01mc@17 2132 meanDBdur = new double[dbH->numFiles];
mas01mc@17 2133 assert(meanDBdur);
mas01mc@17 2134 for(k=0; k<dbH->numFiles; k++){
mas01mc@17 2135 meanDBdur[k]=0.0;
mas01mc@18 2136 for(j=0; j<trackTable[k]-1 ; j++)
mas01mc@17 2137 meanDBdur[k]+=timesTable[j+1]-timesTable[j];
mas01mc@17 2138 meanDBdur[k]/=j;
mas01mc@17 2139 }
mas01mc@17 2140 }
mas01mc@17 2141
mas01mc@17 2142 if(usingQueryPoint)
mas01mc@17 2143 if(queryPoint>numVectors || queryPoint>numVectors-wL+1)
mas01mc@17 2144 error("queryPoint > numVectors-wL+1 in query");
mas01mc@17 2145 else{
mas01cr@60 2146 if(verbosity>1) {
mas01mc@17 2147 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 2148 }
mas01mc@17 2149 query=query+queryPoint*dbH->dim;
mas01mc@17 2150 qNorm=qNorm+queryPoint;
mas01mc@17 2151 numVectors=wL;
mas01mc@17 2152 }
mas01mc@17 2153
mas01mc@17 2154 double ** D = 0; // Differences query and target
mas01mc@17 2155 double ** DD = 0; // Matched filter distance
mas01mc@17 2156
mas01mc@17 2157 D = new double*[numVectors];
mas01mc@17 2158 assert(D);
mas01mc@17 2159 DD = new double*[numVectors];
mas01mc@17 2160 assert(DD);
mas01mc@17 2161
mas01mc@17 2162 gettimeofday(&tv1, NULL);
mas01mc@18 2163 processedTracks=0;
mas01mc@18 2164 unsigned successfulTracks=0;
mas01mc@17 2165
mas01mc@17 2166 double* qp;
mas01mc@17 2167 double* sp;
mas01mc@17 2168 double* dp;
mas01mc@17 2169
mas01mc@18 2170 // build track offset table
mas01mc@18 2171 unsigned *trackOffsetTable = new unsigned[dbH->numFiles];
mas01mc@18 2172 unsigned cumTrack=0;
mas01mc@18 2173 unsigned trackIndexOffset;
mas01mc@17 2174 for(k=0; k<dbH->numFiles;k++){
mas01mc@18 2175 trackOffsetTable[k]=cumTrack;
mas01mc@18 2176 cumTrack+=trackTable[k]*dbH->dim;
mas01mc@17 2177 }
mas01mc@17 2178
mas01mc@17 2179 char nextKey [MAXSTR];
mas01mc@17 2180
mas01mc@17 2181 // chi^2 statistics
mas01mc@17 2182 double sampleCount = 0;
mas01mc@17 2183 double sampleSum = 0;
mas01mc@17 2184 double logSampleSum = 0;
mas01mc@17 2185 double minSample = 1e9;
mas01mc@17 2186 double maxSample = 0;
mas01mc@17 2187
mas01mc@17 2188 // Track loop
mas01mc@18 2189 for(processedTracks=0, track=0 ; processedTracks < dbH->numFiles ; track++, processedTracks++){
mas01mc@17 2190
mas01mc@18 2191 // get trackID from file if using a control file
mas01mc@18 2192 if(trackFile){
mas01mc@18 2193 if(!trackFile->eof()){
mas01mc@18 2194 trackFile->getline(nextKey,MAXSTR);
mas01mc@18 2195 track=getKeyPos(nextKey);
mas01mc@17 2196 }
mas01mc@17 2197 else
mas01mc@17 2198 break;
mas01mc@17 2199 }
mas01mc@17 2200
mas01mc@18 2201 trackOffset=trackOffsetTable[track]; // numDoubles offset
mas01mc@18 2202 trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
mas01mc@17 2203
mas01cr@70 2204 if(sequenceLength<=trackTable[track]){ // test for short sequences
mas01mc@17 2205
mas01cr@60 2206 if(verbosity>7) {
mas01mc@18 2207 cerr << track << "." << trackIndexOffset << "." << trackTable[track] << " | ";cerr.flush();
mas01cr@60 2208 }
mas01cr@60 2209
mas01mc@17 2210 // Sum products matrix
mas01mc@17 2211 for(j=0; j<numVectors;j++){
mas01mc@18 2212 D[j]=new double[trackTable[track]];
mas01mc@17 2213 assert(D[j]);
mas01mc@17 2214
mas01mc@17 2215 }
mas01mc@17 2216
mas01mc@17 2217 // Matched filter matrix
mas01mc@17 2218 for(j=0; j<numVectors;j++){
mas01mc@18 2219 DD[j]=new double[trackTable[track]];
mas01mc@17 2220 assert(DD[j]);
mas01mc@17 2221 }
mas01mc@17 2222
mas01mc@17 2223 // Dot product
mas01mc@17 2224 for(j=0; j<numVectors; j++)
mas01mc@18 2225 for(k=0; k<trackTable[track]; k++){
mas01mc@17 2226 qp=query+j*dbH->dim;
mas01mc@18 2227 sp=dataBuf+trackOffset+k*dbH->dim;
mas01mc@17 2228 DD[j][k]=0.0; // Initialize matched filter array
mas01mc@17 2229 dp=&D[j][k]; // point to correlation cell j,k
mas01mc@17 2230 *dp=0.0; // initialize correlation cell
mas01mc@17 2231 l=dbH->dim; // size of vectors
mas01mc@17 2232 while(l--)
mas01mc@17 2233 *dp+=*qp++**sp++;
mas01mc@17 2234 }
mas01mc@17 2235
mas01mc@17 2236 // Matched Filter
mas01mc@17 2237 // HOP SIZE == 1
mas01mc@17 2238 double* spd;
mas01mc@17 2239 if(HOP_SIZE==1){ // HOP_SIZE = shingleHop
mas01mc@17 2240 for(w=0; w<wL; w++)
mas01mc@17 2241 for(j=0; j<numVectors-w; j++){
mas01mc@17 2242 sp=DD[j];
mas01mc@17 2243 spd=D[j+w]+w;
mas01mc@18 2244 k=trackTable[track]-w;
mas01mc@17 2245 while(k--)
mas01mc@17 2246 *sp+++=*spd++;
mas01mc@17 2247 }
mas01mc@17 2248 }
mas01mc@17 2249
mas01mc@17 2250 else{ // HOP_SIZE != 1
mas01mc@17 2251 for(w=0; w<wL; w++)
mas01mc@17 2252 for(j=0; j<numVectors-w; j+=HOP_SIZE){
mas01mc@17 2253 sp=DD[j];
mas01mc@17 2254 spd=D[j+w]+w;
mas01mc@18 2255 for(k=0; k<trackTable[track]-w; k+=HOP_SIZE){
mas01mc@17 2256 *sp+=*spd;
mas01mc@17 2257 sp+=HOP_SIZE;
mas01mc@17 2258 spd+=HOP_SIZE;
mas01mc@17 2259 }
mas01mc@17 2260 }
mas01mc@17 2261 }
mas01mc@17 2262
mas01cr@60 2263 if(verbosity>3 && usingTimes) {
mas01mc@18 2264 cerr << "meanQdur=" << meanQdur << " meanDBdur=" << meanDBdur[track] << endl;
mas01mc@17 2265 cerr.flush();
mas01mc@17 2266 }
mas01mc@17 2267
mas01mc@17 2268 if(!usingTimes ||
mas01mc@17 2269 (usingTimes
mas01mc@18 2270 && fabs(meanDBdur[track]-meanQdur)<meanQdur*timesTol)){
mas01mc@17 2271
mas01cr@60 2272 if(verbosity>3 && usingTimes) {
mas01mc@17 2273 cerr << "within duration tolerance." << endl;
mas01mc@17 2274 cerr.flush();
mas01mc@17 2275 }
mas01mc@17 2276
mas01mc@17 2277 // Search for minimum distance by shingles (concatenated vectors)
mas01cr@70 2278 for(j=0;j<=numVectors-wL;j+=HOP_SIZE)
mas01cr@70 2279 for(k=0;k<=trackTable[track]-wL;k+=HOP_SIZE){
mas01mc@18 2280 thisDist=2-(2/(qNorm[j]*sNorm[trackIndexOffset+k]))*DD[j][k];
mas01cr@60 2281 if(verbosity>10) {
mas01mc@18 2282 cerr << thisDist << " " << qNorm[j] << " " << sNorm[trackIndexOffset+k] << endl;
mas01cr@60 2283 }
mas01mc@17 2284 // Gather chi^2 statistics
mas01mc@17 2285 if(thisDist<minSample)
mas01mc@17 2286 minSample=thisDist;
mas01mc@17 2287 else if(thisDist>maxSample)
mas01mc@17 2288 maxSample=thisDist;
mas01mc@17 2289 if(thisDist>1e-9){
mas01mc@17 2290 sampleCount++;
mas01mc@17 2291 sampleSum+=thisDist;
mas01mc@17 2292 logSampleSum+=log(thisDist);
mas01mc@17 2293 }
mas01mc@17 2294
mas01mc@18 2295 // diffL2 = fabs(qNorm[j] - sNorm[trackIndexOffset+k]);
mas01mc@17 2296 // Power test
mas01mc@17 2297 if(!USE_THRESH ||
mas01mc@17 2298 // Threshold on mean L2 of Q and S sequences
mas01mc@18 2299 (USE_THRESH && qNorm[j]>SILENCE_THRESH && sNorm[trackIndexOffset+k]>SILENCE_THRESH &&
mas01mc@17 2300 // Are both query and target windows above mean energy?
mas01mc@18 2301 (qNorm[j]>qMeanL2*.25 && sNorm[trackIndexOffset+k]>sMeanL2[track]*.25))) // && diffL2 < DIFF_THRESH )))
mas01mc@17 2302 thisDist=thisDist; // Computed above
mas01mc@17 2303 else
mas01mc@17 2304 thisDist=1000000.0;
mas01mc@17 2305 if(thisDist>=0 && thisDist<=radius){
mas01mc@17 2306 distances[0]++; // increment count
mas01mc@18 2307 break; // only need one track point per query point
mas01mc@17 2308 }
mas01mc@17 2309 }
mas01mc@17 2310 // How many points were below threshold ?
mas01mc@17 2311 thisDist=distances[0];
mas01mc@17 2312
mas01mc@17 2313 // Let's see the distances then...
mas01cr@60 2314 if(verbosity>3) {
mas01mc@18 2315 cerr << fileTable+track*O2_FILETABLESIZE << " " << thisDist << endl;
mas01cr@60 2316 }
mas01mc@17 2317
mas01mc@18 2318 // All the track stuff goes here
mas01mc@18 2319 n=trackNN;
mas01mc@17 2320 while(n--){
mas01mc@18 2321 if(thisDist>trackDistances[n]){
mas01mc@18 2322 if((n==0 || thisDist<=trackDistances[n-1])){
mas01mc@17 2323 // Copy all values above up the queue
mas01mc@18 2324 for( l=trackNN-1 ; l > n ; l--){
mas01mc@18 2325 trackDistances[l]=trackDistances[l-1];
mas01mc@18 2326 trackQIndexes[l]=trackQIndexes[l-1];
mas01mc@18 2327 trackSIndexes[l]=trackSIndexes[l-1];
mas01mc@18 2328 trackIDs[l]=trackIDs[l-1];
mas01mc@17 2329 }
mas01mc@18 2330 trackDistances[n]=thisDist;
mas01mc@18 2331 trackQIndexes[n]=qIndexes[0];
mas01mc@18 2332 trackSIndexes[n]=sIndexes[0];
mas01mc@18 2333 successfulTracks++;
mas01mc@18 2334 trackIDs[n]=track;
mas01mc@17 2335 break;
mas01mc@17 2336 }
mas01mc@17 2337 }
mas01mc@17 2338 else
mas01mc@17 2339 break;
mas01mc@17 2340 }
mas01mc@17 2341 } // Duration match
mas01mc@17 2342
mas01mc@18 2343 // Clean up current track
mas01mc@17 2344 if(D!=NULL){
mas01mc@17 2345 for(j=0; j<numVectors; j++)
mas01mc@17 2346 delete[] D[j];
mas01mc@17 2347 }
mas01mc@17 2348
mas01mc@17 2349 if(DD!=NULL){
mas01mc@17 2350 for(j=0; j<numVectors; j++)
mas01mc@17 2351 delete[] DD[j];
mas01mc@17 2352 }
mas01mc@17 2353 }
mas01mc@18 2354 // per-track reset array values
mas01mc@17 2355 for(unsigned k=0; k<pointNN; k++){
mas01mc@17 2356 distances[k]=0.0;
mas01mc@17 2357 qIndexes[k]=~0;
mas01mc@17 2358 sIndexes[k]=~0;
mas01mc@17 2359 }
mas01mc@17 2360 }
mas01mc@17 2361
mas01mc@17 2362 gettimeofday(&tv2,NULL);
mas01cr@60 2363 if(verbosity>1) {
mas01mc@18 2364 cerr << endl << "processed tracks :" << processedTracks << " matched tracks: " << successfulTracks << " elapsed time:"
mas01mc@17 2365 << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01mc@17 2366 cerr << "sampleCount: " << sampleCount << " sampleSum: " << sampleSum << " logSampleSum: " << logSampleSum
mas01mc@17 2367 << " minSample: " << minSample << " maxSample: " << maxSample << endl;
mas01mc@17 2368 }
mas01mc@17 2369
mas01mc@17 2370 if(adbQueryResult==0){
mas01cr@60 2371 if(verbosity>1) {
mas01mc@17 2372 cerr<<endl;
mas01cr@60 2373 }
mas01mc@17 2374 // Output answer
mas01mc@17 2375 // Loop over nearest neighbours
mas01mc@18 2376 for(k=0; k < min(trackNN,successfulTracks); k++)
mas01mc@18 2377 cout << fileTable+trackIDs[k]*O2_FILETABLESIZE << " " << trackDistances[k] << endl;
mas01mc@17 2378 }
mas01mc@17 2379 else{ // Process Web Services Query
mas01mc@18 2380 int listLen = min(trackNN, processedTracks);
mas01mc@17 2381 adbQueryResult->__sizeRlist=listLen;
mas01mc@17 2382 adbQueryResult->__sizeDist=listLen;
mas01mc@17 2383 adbQueryResult->__sizeQpos=listLen;
mas01mc@17 2384 adbQueryResult->__sizeSpos=listLen;
mas01mc@17 2385 adbQueryResult->Rlist= new char*[listLen];
mas01mc@17 2386 adbQueryResult->Dist = new double[listLen];
mas01cr@86 2387 adbQueryResult->Qpos = new unsigned int[listLen];
mas01cr@86 2388 adbQueryResult->Spos = new unsigned int[listLen];
mas01cr@59 2389 for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){
mas01mc@17 2390 adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR];
mas01mc@18 2391 adbQueryResult->Dist[k]=trackDistances[k];
mas01mc@18 2392 adbQueryResult->Qpos[k]=trackQIndexes[k];
mas01mc@18 2393 adbQueryResult->Spos[k]=trackSIndexes[k];
mas01mc@18 2394 sprintf(adbQueryResult->Rlist[k], "%s", fileTable+trackIDs[k]*O2_FILETABLESIZE);
mas01mc@17 2395 }
mas01mc@17 2396 }
mas01mc@17 2397
mas01mc@17 2398
mas01mc@17 2399 // Clean up
mas01mc@18 2400 if(trackOffsetTable)
mas01mc@18 2401 delete[] trackOffsetTable;
mas01mc@17 2402 if(queryCopy)
mas01mc@17 2403 delete[] queryCopy;
mas01mc@17 2404 //if(qNorm)
mas01mc@17 2405 //delete qNorm;
mas01mc@17 2406 if(D)
mas01mc@17 2407 delete[] D;
mas01mc@17 2408 if(DD)
mas01mc@17 2409 delete[] DD;
mas01mc@17 2410 if(timesdata)
mas01mc@17 2411 delete[] timesdata;
mas01mc@17 2412 if(meanDBdur)
mas01mc@17 2413 delete[] meanDBdur;
mas01mc@17 2414
mas01mc@17 2415
mas01mc@17 2416 }
mas01mc@17 2417
mas01cr@0 2418 // Unit norm block of features
mas01cr@0 2419 void audioDB::unitNorm(double* X, unsigned dim, unsigned n, double* qNorm){
mas01cr@0 2420 unsigned d;
mas01cr@59 2421 double L2, *p;
mas01cr@60 2422 if(verbosity>2) {
mas01cr@0 2423 cerr << "norming " << n << " vectors...";cerr.flush();
mas01cr@60 2424 }
mas01cr@0 2425 while(n--){
mas01cr@0 2426 p=X;
mas01cr@0 2427 L2=0.0;
mas01cr@0 2428 d=dim;
mas01cr@0 2429 while(d--){
mas01cr@0 2430 L2+=*p**p;
mas01cr@0 2431 p++;
mas01cr@0 2432 }
mas01mc@17 2433 /* L2=sqrt(L2);*/
mas01cr@0 2434 if(qNorm)
mas01cr@0 2435 *qNorm++=L2;
mas01mc@17 2436 /*
mas01cr@0 2437 oneOverL2 = 1.0/L2;
mas01cr@0 2438 d=dim;
mas01cr@0 2439 while(d--){
mas01cr@0 2440 *X*=oneOverL2;
mas01cr@0 2441 X++;
mas01mc@17 2442 */
mas01mc@17 2443 X+=dim;
mas01cr@0 2444 }
mas01cr@60 2445 if(verbosity>2) {
mas01cr@0 2446 cerr << "done..." << endl;
mas01cr@60 2447 }
mas01cr@0 2448 }
mas01cr@0 2449
mas01cr@0 2450 // Unit norm block of features
mas01cr@0 2451 void audioDB::unitNormAndInsertL2(double* X, unsigned dim, unsigned n, unsigned append=0){
mas01cr@0 2452 unsigned d;
mas01cr@59 2453 double *p;
mas01cr@0 2454 unsigned nn = n;
mas01cr@0 2455
mas01cr@0 2456 assert(l2normTable);
mas01cr@0 2457
mas01cr@0 2458 if( !append && (dbH->flags & O2_FLAG_L2NORM) )
mas01cr@0 2459 error("Database is already L2 normed", "automatic norm on insert is enabled");
mas01cr@0 2460
mas01cr@60 2461 if(verbosity>2) {
mas01cr@0 2462 cerr << "norming " << n << " vectors...";cerr.flush();
mas01cr@60 2463 }
mas01cr@0 2464
mas01cr@0 2465 double* l2buf = new double[n];
mas01cr@0 2466 double* l2ptr = l2buf;
mas01cr@0 2467 assert(l2buf);
mas01cr@0 2468 assert(X);
mas01cr@0 2469
mas01cr@0 2470 while(nn--){
mas01cr@0 2471 p=X;
mas01cr@0 2472 *l2ptr=0.0;
mas01cr@0 2473 d=dim;
mas01cr@0 2474 while(d--){
mas01cr@0 2475 *l2ptr+=*p**p;
mas01cr@0 2476 p++;
mas01cr@0 2477 }
mas01mc@17 2478 l2ptr++;
mas01mc@17 2479 /*
mas01mc@17 2480 oneOverL2 = 1.0/(*l2ptr++);
mas01mc@17 2481 d=dim;
mas01mc@17 2482 while(d--){
mas01cr@0 2483 *X*=oneOverL2;
mas01cr@0 2484 X++;
mas01mc@17 2485 }
mas01mc@17 2486 */
mas01mc@17 2487 X+=dim;
mas01cr@0 2488 }
mas01cr@0 2489 unsigned offset;
mas01cr@84 2490 if(append) {
mas01cr@84 2491 // FIXME: a hack, a very palpable hack: the vectors have already
mas01cr@84 2492 // been inserted, and dbH->length has already been updated. We
mas01cr@84 2493 // need to subtract off again the number of vectors that we've
mas01cr@84 2494 // inserted this time...
mas01cr@84 2495 offset=(dbH->length/(dbH->dim*sizeof(double)))-n; // number of vectors
mas01cr@84 2496 } else {
mas01cr@0 2497 offset=0;
mas01cr@84 2498 }
mas01cr@0 2499 memcpy(l2normTable+offset, l2buf, n*sizeof(double));
mas01cr@0 2500 if(l2buf)
mas01mc@17 2501 delete[] l2buf;
mas01cr@60 2502 if(verbosity>2) {
mas01cr@0 2503 cerr << "done..." << endl;
mas01cr@60 2504 }
mas01cr@0 2505 }
mas01cr@0 2506
mas01cr@0 2507
mas01cr@0 2508 // Start an audioDB server on the host
mas01cr@0 2509 void audioDB::startServer(){
mas01cr@0 2510 struct soap soap;
mas01cr@0 2511 int m, s; // master and slave sockets
mas01cr@0 2512 soap_init(&soap);
mas01cr@92 2513 // FIXME: largely this use of SO_REUSEADDR is to make writing (and
mas01cr@92 2514 // running) test cases more convenient, so that multiple test runs
mas01cr@92 2515 // in close succession don't fail because of a bin() error.
mas01cr@92 2516 // Investigate whether there are any potential drawbacks in this,
mas01cr@92 2517 // and also whether there's a better way to write the tests. --
mas01cr@92 2518 // CSR, 2007-10-03
mas01cr@92 2519 soap.bind_flags |= SO_REUSEADDR;
mas01cr@0 2520 m = soap_bind(&soap, NULL, port, 100);
mas01cr@0 2521 if (m < 0)
mas01cr@0 2522 soap_print_fault(&soap, stderr);
mas01cr@0 2523 else
mas01cr@0 2524 {
mas01cr@0 2525 fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
mas01cr@0 2526 for (int i = 1; ; i++)
mas01cr@0 2527 {
mas01cr@0 2528 s = soap_accept(&soap);
mas01cr@0 2529 if (s < 0)
mas01cr@0 2530 {
mas01cr@0 2531 soap_print_fault(&soap, stderr);
mas01cr@0 2532 break;
mas01cr@0 2533 }
mas01cr@75 2534 fprintf(stderr, "%d: accepted connection from IP=%lu.%lu.%lu.%lu socket=%d\n", i,
mas01cr@0 2535 (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
mas01cr@0 2536 if (soap_serve(&soap) != SOAP_OK) // process RPC request
mas01cr@0 2537 soap_print_fault(&soap, stderr); // print error
mas01cr@0 2538 fprintf(stderr, "request served\n");
mas01cr@0 2539 soap_destroy(&soap); // clean up class instances
mas01cr@0 2540 soap_end(&soap); // clean up everything and close socket
mas01cr@0 2541 }
mas01cr@0 2542 }
mas01cr@0 2543 soap_done(&soap); // close master socket and detach environment
mas01cr@0 2544 }
mas01cr@0 2545
mas01cr@0 2546
mas01cr@0 2547 // web services
mas01cr@0 2548
mas01cr@0 2549 // SERVER SIDE
mas01cr@76 2550 int adb__status(struct soap* soap, xsd__string dbName, adb__statusResult &adbStatusResult){
mas01cr@21 2551 char* const argv[]={"audioDB",COM_STATUS,"-d",dbName};
mas01cr@21 2552 const unsigned argc = 4;
mas01cr@77 2553 try {
mas01cr@77 2554 audioDB(argc, argv, &adbStatusResult);
mas01cr@77 2555 return SOAP_OK;
mas01cr@77 2556 } catch(char *err) {
mas01cr@77 2557 soap_receiver_fault(soap, err, "");
mas01cr@77 2558 return SOAP_FAULT;
mas01cr@77 2559 }
mas01cr@0 2560 }
mas01cr@0 2561
mas01cr@0 2562 // Literal translation of command line to web service
mas01cr@0 2563
mas01mc@18 2564 int adb__query(struct soap* soap, xsd__string dbName, xsd__string qKey, xsd__string keyList, xsd__string timesFileName, xsd__int qType, xsd__int qPos, xsd__int pointNN, xsd__int trackNN, xsd__int seqLen, adb__queryResult &adbQueryResult){
mas01cr@0 2565 char queryType[256];
mas01cr@0 2566 for(int k=0; k<256; k++)
mas01cr@0 2567 queryType[k]='\0';
mas01cr@0 2568 if(qType == O2_FLAG_POINT_QUERY)
mas01cr@0 2569 strncpy(queryType, "point", strlen("point"));
mas01cr@0 2570 else if (qType == O2_FLAG_SEQUENCE_QUERY)
mas01cr@0 2571 strncpy(queryType, "sequence", strlen("sequence"));
mas01mc@18 2572 else if(qType == O2_FLAG_TRACK_QUERY)
mas01mc@18 2573 strncpy(queryType,"track", strlen("track"));
mas01cr@0 2574 else
mas01cr@0 2575 strncpy(queryType, "", strlen(""));
mas01cr@0 2576
mas01cr@0 2577 if(pointNN==0)
mas01cr@0 2578 pointNN=10;
mas01mc@18 2579 if(trackNN==0)
mas01mc@18 2580 trackNN=10;
mas01cr@0 2581 if(seqLen==0)
mas01cr@0 2582 seqLen=16;
mas01cr@0 2583
mas01cr@0 2584 char qPosStr[256];
mas01cr@0 2585 sprintf(qPosStr, "%d", qPos);
mas01cr@0 2586 char pointNNStr[256];
mas01cr@0 2587 sprintf(pointNNStr,"%d",pointNN);
mas01mc@18 2588 char trackNNStr[256];
mas01mc@18 2589 sprintf(trackNNStr,"%d",trackNN);
mas01cr@0 2590 char seqLenStr[256];
mas01cr@0 2591 sprintf(seqLenStr,"%d",seqLen);
mas01cr@0 2592
mas01cr@0 2593 const char* argv[] ={
mas01cr@0 2594 "./audioDB",
mas01cr@0 2595 COM_QUERY,
mas01cr@0 2596 queryType, // Need to pass a parameter
mas01cr@0 2597 COM_DATABASE,
mas01cr@0 2598 dbName,
mas01cr@0 2599 COM_FEATURES,
mas01cr@0 2600 qKey,
mas01cr@0 2601 COM_KEYLIST,
mas01cr@0 2602 keyList==0?"":keyList,
mas01cr@0 2603 COM_TIMES,
mas01cr@0 2604 timesFileName==0?"":timesFileName,
mas01cr@0 2605 COM_QPOINT,
mas01cr@0 2606 qPosStr,
mas01cr@0 2607 COM_POINTNN,
mas01cr@0 2608 pointNNStr,
mas01mc@18 2609 COM_TRACKNN,
mas01mc@18 2610 trackNNStr, // Need to pass a parameter
mas01cr@0 2611 COM_SEQLEN,
mas01cr@0 2612 seqLenStr
mas01cr@0 2613 };
mas01cr@0 2614
mas01cr@0 2615 const unsigned argc = 19;
mas01cr@79 2616 try {
mas01cr@79 2617 audioDB(argc, (char* const*)argv, &adbQueryResult);
mas01cr@79 2618 return SOAP_OK;
mas01cr@79 2619 } catch (char *err) {
mas01cr@79 2620 soap_receiver_fault(soap, err, "");
mas01cr@79 2621 return SOAP_FAULT;
mas01cr@79 2622 }
mas01cr@0 2623 }
mas01cr@0 2624
mas01cr@0 2625 int main(const unsigned argc, char* const argv[]){
mas01cr@0 2626 audioDB(argc, argv);
mas01cr@0 2627 }
mas01cr@104 2628