mas01cr@239
|
1 #include "audioDB.h"
|
mas01cr@385
|
2 extern "C" {
|
mas01cr@385
|
3 #include "audioDB_API.h"
|
mas01cr@385
|
4 }
|
mas01cr@410
|
5 #include "audioDB-internals.h"
|
mas01cr@410
|
6
|
mas01cr@239
|
7 /* Make a new database.
|
mas01cr@239
|
8
|
mas01cr@407
|
9 IF size(featuredata) < O2_LARGE_ADB_SIZE
|
mas01cr@239
|
10 The database consists of:
|
mas01cr@239
|
11
|
mas01cr@239
|
12 * a header (see dbTableHeader struct definition);
|
mas01cr@239
|
13 * keyTable: list of keys of tracks;
|
mas01cr@239
|
14 * trackTable: Maps implicit feature index to a feature vector
|
mas01cr@239
|
15 matrix (sizes of tracks)
|
mas01cr@239
|
16 * featureTable: Lots of doubles;
|
mas01cr@239
|
17 * timesTable: (start,end) time points for each feature vector;
|
mas01cr@239
|
18 * powerTable: associated power for each feature vector;
|
mas01cr@239
|
19 * l2normTable: squared l2norms for each feature vector.
|
mas01cr@407
|
20
|
mas01mc@324
|
21 ELSE the database consists of:
|
mas01cr@407
|
22
|
mas01mc@324
|
23 * a header (see dbTableHeader struct definition);
|
mas01mc@324
|
24 * keyTable: list of keys of tracks
|
mas01mc@324
|
25 * trackTable: sizes of tracks
|
mas01mc@324
|
26 * featureTable: list of feature file names
|
mas01mc@324
|
27 * timesTable: list of times file names
|
mas01mc@324
|
28 * powerTable: list of power file names
|
mas01mc@324
|
29
|
mas01cr@239
|
30 */
|
mas01cr@239
|
31
|
mas01cr@407
|
32 adb_t *audiodb_create(const char *path, unsigned datasize, unsigned ntracks, unsigned datadim) {
|
mas01cr@407
|
33 int fd;
|
mas01cr@407
|
34 adb_header_t *header = 0;
|
mas01cr@407
|
35 off_t databytes, auxbytes;
|
mas01cr@407
|
36 if(datasize == 0) {
|
mas01cr@407
|
37 datasize = O2_DEFAULT_DATASIZE;
|
mas01cr@407
|
38 }
|
mas01cr@407
|
39 if(ntracks == 0) {
|
mas01cr@407
|
40 ntracks = O2_DEFAULT_NTRACKS;
|
mas01cr@407
|
41 }
|
mas01cr@407
|
42 if(datadim == 0) {
|
mas01cr@407
|
43 datadim = O2_DEFAULT_DATADIM;
|
mas01cr@407
|
44 }
|
mas01cr@239
|
45
|
mas01cr@407
|
46 if ((fd = open(path, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) {
|
mas01cr@407
|
47 goto error;
|
mas01cr@407
|
48 }
|
mas01cr@407
|
49 if (acquire_lock(fd, true)) {
|
mas01cr@407
|
50 goto error;
|
mas01cr@407
|
51 }
|
mas01cr@389
|
52
|
mas01cr@407
|
53 header = (adb_header_t *) malloc(sizeof(adb_header_t));
|
mas01cr@407
|
54 if(!header) {
|
mas01cr@407
|
55 goto error;
|
mas01cr@407
|
56 }
|
mas01cr@389
|
57
|
mas01cr@407
|
58 // Initialize header
|
mas01cr@407
|
59 header->magic = O2_MAGIC;
|
mas01cr@407
|
60 header->version = O2_FORMAT_VERSION;
|
mas01cr@407
|
61 header->numFiles = 0;
|
mas01cr@407
|
62 header->dim = 0;
|
mas01cr@407
|
63 header->flags = 0;
|
mas01cr@407
|
64 header->headerSize = O2_HEADERSIZE;
|
mas01cr@407
|
65 header->length = 0;
|
mas01cr@407
|
66 header->fileTableOffset = ALIGN_PAGE_UP(O2_HEADERSIZE);
|
mas01cr@407
|
67 header->trackTableOffset = ALIGN_PAGE_UP(header->fileTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks);
|
mas01cr@407
|
68 header->dataOffset = ALIGN_PAGE_UP(header->trackTableOffset + O2_TRACKTABLE_ENTRY_SIZE*ntracks);
|
mas01cr@407
|
69
|
mas01cr@407
|
70 databytes = ((off_t) datasize) * 1024 * 1024;
|
mas01cr@407
|
71 auxbytes = databytes / datadim;
|
mas01cr@407
|
72
|
mas01cr@458
|
73 /* FIXME: what's going on here? There are two distinct preprocessor
|
mas01cr@458
|
74 constants (O2_LSH_N_POINT_BITS, LSH_N_POINT_BITS); a third is
|
mas01cr@458
|
75 presumably some default (O2_DEFAULT_LSH_N_POINT_BITS), and then
|
mas01cr@458
|
76 there's this magic 28 bits [which needs to be the same as the 28
|
mas01cr@458
|
77 in audiodb_lsh_n_point_bits()]. Should this really be part of
|
mas01cr@458
|
78 the flags structure at all? Putting it elsewhere will of course
|
mas01cr@458
|
79 break backwards compatibility, unless 14 is the only value that's
|
mas01cr@458
|
80 been used anywhere... */
|
mas01cr@407
|
81
|
mas01cr@407
|
82 // For backward-compatibility, Record the point-encoding parameter for LSH indexing in the adb header
|
mas01cr@407
|
83 // If this value is 0 then it will be set to 14
|
mas01cr@407
|
84
|
mas01mc@324
|
85 #if O2_LSH_N_POINT_BITS > 15
|
mas01mc@324
|
86 #error "AudioDB Compile ERROR: consistency check of O2_LSH_POINT_BITS failed (>15)"
|
mas01mc@324
|
87 #endif
|
mas01cr@407
|
88
|
mas01cr@407
|
89 header->flags |= LSH_N_POINT_BITS << 28;
|
mas01cr@407
|
90
|
mas01cr@407
|
91 // If database will fit in a single file the vectors are copied into the AudioDB instance
|
mas01cr@407
|
92 // Else all the vectors are left on the FileSystem and we use the dataOffset as storage
|
mas01cr@407
|
93 // for the location of the features, powers and times files (assuming that arbitrary keys are used for the fileTable)
|
mas01cr@407
|
94 if(ntracks<O2_LARGE_ADB_NTRACKS && datasize<O2_LARGE_ADB_SIZE){
|
mas01cr@407
|
95 header->timesTableOffset = ALIGN_PAGE_UP(header->dataOffset + databytes);
|
mas01cr@407
|
96 header->powerTableOffset = ALIGN_PAGE_UP(header->timesTableOffset + 2*auxbytes);
|
mas01cr@407
|
97 header->l2normTableOffset = ALIGN_PAGE_UP(header->powerTableOffset + auxbytes);
|
mas01cr@407
|
98 header->dbSize = ALIGN_PAGE_UP(header->l2normTableOffset + auxbytes);
|
mas01cr@407
|
99 } else { // Create LARGE_ADB, features and powers kept on filesystem
|
mas01cr@407
|
100 header->flags |= O2_FLAG_LARGE_ADB;
|
mas01cr@407
|
101 header->timesTableOffset = ALIGN_PAGE_UP(header->dataOffset + O2_FILETABLE_ENTRY_SIZE*ntracks);
|
mas01cr@407
|
102 header->powerTableOffset = ALIGN_PAGE_UP(header->timesTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks);
|
mas01cr@407
|
103 header->l2normTableOffset = ALIGN_PAGE_UP(header->powerTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks);
|
mas01cr@407
|
104 header->dbSize = header->l2normTableOffset;
|
mas01cr@407
|
105 }
|
mas01cr@407
|
106
|
mas01cr@410
|
107 write_or_goto_error(fd, header, O2_HEADERSIZE);
|
mas01cr@407
|
108
|
mas01cr@407
|
109 // go to the location corresponding to the last byte
|
mas01cr@407
|
110 if (lseek (fd, header->dbSize - 1, SEEK_SET) == -1) {
|
mas01cr@407
|
111 goto error;
|
mas01cr@407
|
112 }
|
mas01cr@407
|
113
|
mas01cr@407
|
114 // write a dummy byte at the last location
|
mas01cr@410
|
115 write_or_goto_error(fd, "", 1);
|
mas01cr@389
|
116
|
mas01cr@407
|
117 free(header);
|
mas01cr@407
|
118 return audiodb_open(path, O_RDWR);
|
mas01cr@389
|
119
|
mas01cr@407
|
120 error:
|
mas01cr@407
|
121 if(header) {
|
mas01cr@390
|
122 free(header);
|
mas01mc@324
|
123 }
|
mas01cr@407
|
124 return NULL;
|
mas01cr@239
|
125 }
|