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