comparison core/magnatagatune/MTTAudioFeatureDBgen.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:e9a9cd732c1e
1 classdef MTTAudioFeatureDBgen < handle
2
3 % ---
4 % the database is stored as a global variable
5 % ---
6
7 properties (Hidden)
8
9 % feature databases
10 featuredb;
11
12 commondb;
13
14 feature_type;
15 feature_params;
16
17 % unfortunately we just can have one clip type at a time
18 clip_type;
19 end
20
21
22 properties (Hidden)
23
24 % ---
25 % We use a "db_magnaaudiofeat_xxx" class pointer for all the loaded features,
26 % which is supposed to work like a cache.
27 % my_dbpos links to the position of this feature in the db.
28 % ---
29
30 % database hash
31 featuredb_hash;
32 end
33
34 % ---
35 % member functions
36 % ---
37 methods
38
39 % constructor
40 function db = MTTAudioFeatureDBgen(type, matfile)
41
42 if nargin >= 1
43
44 % ---
45 % we test for correct type by
46 % using an call to the empty arg constructor function
47 % ---
48 try
49 feval(type);
50
51 catch err
52 fprintf('%s\n', err.message);
53 error('The specified class does not provide an constructor')
54 end
55 db.feature_type = type;
56
57 if nargin >=2 && ~isempty(dir(matfile))
58
59
60 % import database if filename given
61 db.import(matfile);
62 end
63
64 end
65
66 % try to load a standard db from mat file?
67 end
68
69 % ---
70 % database retrieval.
71 % this should return a handle to a feature class pointing in this
72 % global feature database.
73 %
74 % parameters can be passed via the varargin parameter
75 % ---
76 function features = get_features(db, clip, varargin)
77
78 % ---
79 % TODO: error checking and processing
80 % ---
81
82 % ---
83 % prepare for multiple clips
84 % ---
85 if numel(clip) > 1
86
87 % iterate for all the found clips
88 features = feval(db.feature_type);
89 for i = 1:numel(clip)
90 features(i) = get_features(db, clip(i), varargin{:});
91 end
92 else
93 % ---
94 % single feature extraction
95 % ---
96
97 pos = db.get_clip_pos(clip);
98 if ~pos
99
100 % assign new database position
101 pos = db.get_next_pos();
102
103 % call feature constructor
104 features = feval(db.feature_type, db, varargin{:});
105
106 % extract / load feature data
107
108 cprint(2 ,'Extracting %s for clip %d \n', db.feature_type, clip.id());
109
110 if isempty( db.featuredb)
111
112 db.featuredb = features.extract(clip);
113 else
114
115 db.featuredb(pos) = features.extract(clip);
116 end
117 % ---
118 % NOTE:
119 % IF WE ARE SURE THAT EVERYTHING HAS WORKED OUT FINE:
120 % assign new database position in cache
121 % ---
122 db.set_pos(pos, clip);
123
124 % ---
125 % NOTE: feature objects are directly linked to DB
126 % positions
127 % ---
128 features.assign(pos);
129 else
130
131 % just return the cached link
132 features = feval(db.feature_type, db, pos);
133 end
134
135 % ---
136 % finalise features if possible (commondb not empty)
137 % ---
138 if ~isempty(db.commondb) && isempty(features.data.final) && ...
139 ismethod(features,'finalise')
140
141 % call finalise
142 features.finalise();
143 end
144
145 % set clip type of the db
146 db.clip_type = class(clip(1));
147
148 % get last params
149 db.feature_params = features(1).my_params;
150 end
151 end
152
153 function set_common(db, common)
154 % sets the common database to input
155
156 if isempty(db.commondb)
157
158 cprint(2, 'Setting common feature values\n');
159 else
160
161 cprint(1, 'Common feature values changed');
162 end
163
164 db.commondb = common;
165 end
166
167 function export(db, matfile, clips)
168 % saves featuredb to matlab data file
169
170 global globalvars;
171 % save revision for later version and compability control
172 info.creatorrev = globalvars.camir.revision;
173
174 cprint(2, 'Exporting %s database to %s ...\n', db.feature_type, matfile);
175 if nargin == 3
176 % ---
177 % TODO: create new hash
178 % ---
179 for i = 1:numel(clips)
180 pos(i) = db.get_clip_pos(clips(i));
181
182 if pos(i) == 0
183 error('Corrupted database');
184 end
185 end
186
187 % get specific data set
188 featuredb = db.featuredb(pos);
189
190 featuredb_hash = db.featuredb_hash(pos);
191
192 else
193 featuredb = db.featuredb;
194
195 featuredb_hash = db.featuredb_hash;
196 end
197
198 commondb = db.commondb;
199
200 feature_type = db.feature_type;
201
202 % ---
203 % save clip type as well
204 % NOTE: this only works if all clips have the same type (e.g.
205 % CASIMIRClip or MTTclip
206 % ---
207 clip_type = class(clips(1));
208
209 save(matfile, 'featuredb', 'commondb', 'feature_type', 'featuredb_hash', 'clip_type');
210 end
211
212 function [features, clips] = import(db, matfile, type)
213 % gets featuredb from matlab data file
214
215 cprint(2, 'importing features from %s', matfile)
216 load(matfile,'-MAT');
217
218 if ~strcmp(feature_type, db.feature_type)
219
220 error('feature type of db to import does not match');
221 end
222
223 % ---
224 % TODO / FIXME: check parameter hash before importing
225 % ---
226
227 % if db.size() > 0
228 %
229 % % get a feature param from the db;
230 % last_pos = db.get_last_pos;
231 % dummyparams = db.featuredb(last_pos).info.params;
232 %
233 % % ---
234 % % construct a dummy feature and compare parameters to
235 % % the params in the database
236 % % ---
237 % dummyclip = MTTClip(db.featuredb_hash(last_pos));
238 % dummyfeat = db.get_features(dummyclip, dummyparams);
239 %
240 % if ~dummybsm.eq_params(fparams(i))
241 %
242 % db_magnaaudiofeat_basicsm.reset;
243 % end
244 %
245 % end
246
247 if exist('clip_type','var')
248 clips = feval(clip_type,featuredb_hash);
249 db.clip_type = clip_type;
250 else
251 clips = MTTClip(featuredb_hash);
252 db.clip_type = 'MTTClip';
253 end
254
255 % ---
256 % import features individually into db
257 % ---
258
259 for i = 1:numel(clips)
260
261 % test if database already contains clip
262 if ~db.get_clip_pos(clips(i));
263
264 % get position for this database
265 pos = db.get_next_pos();
266
267 % copy values
268 if ~isempty(db.featuredb)
269
270 db.featuredb(pos) = featuredb(i);
271 elseif pos == 1;
272
273 db.featuredb = featuredb(i);
274 else
275
276 error ('Corrupted database');
277 end
278 % update hash
279 db.set_pos(pos, clips(i));
280 end
281 end
282
283 % Set common features
284 db.set_common(commondb);
285
286 if nargout > 0
287 % retrieve features;
288 features = get_features(db, clips);
289 end
290
291 end
292
293 function [matfile] = load(db, featuretype, fparams, clips)
294 % this is the new implementation of MTTAudiofeature_load
295
296 % get filename
297 matfile = MTTAudioFeatureDBgen.get_db_filename(featuretype, fparams,clips);
298
299 % does it exist?
300 if exist(matfile,'file') == 2
301 import(db, matfile);
302 else
303 matfile= [];
304 end
305 end
306
307 function [matfile] = save(db)
308 % this is the new implementation of MTTAudiofeature_load
309
310 % get clips
311 clips = feval(db.clip_type,db.featuredb_hash);
312
313 % get filename
314 matfile = MTTAudioFeatureDBgen.get_db_filename(db.feature_type, db.feature_params ,clips);
315
316 % does it exist?
317 if exist(matfile,'file') == 2
318 warning 'overwriting feature file for this config'
319 end
320
321 % save params in xml
322 xml_save(sprintf('%s.xml', substr(matfile, 0, -4)),db.feature_params);
323
324 %export features
325 export(db, matfile, clips);
326 end
327
328 function remove_features(db, clip)
329 % weakly deletes clip features from db
330
331 clear_pos(clip);
332 end
333
334 function delete(db)
335 % ---
336 % probably not anything to do here, as we want to
337 % keep the db!
338 % see static method destroy
339 % ---
340 end
341
342 function reset(db)
343 % ---
344 % deletes all the cached data and destroys the
345 % global feature database
346 % ---
347 db.commondb = [];
348 db.featuredb = [];
349 db.featuredb_hash = [];
350 end
351
352 function out = size(db)
353 % returns the number of features saved in this db
354
355 out = sum(db.featuredb_hash > 0);
356 end
357
358 function memory(db)
359 % returns size of whole db in bytes
360
361 % ---
362 % TODO: Make this work
363 % ---
364
365 fprintf(' \n This db contains feature sets for %d clips\n ',numel(db.featuredb_hash))
366 % get local copies of data
367 featuredb = db.featuredb;
368 featuredb_hash = db.featuredb_hash;
369 commondb = db.commondb;
370
371 whos('featuredb', 'featuredb_hash', 'commondb')
372 end
373 end
374
375 % ---
376 % private functions
377 % ---
378 methods (Hidden)
379
380 % ---
381 % Hash functions
382 % ---
383 function out = get_clip_pos(db, clip)
384 % should become database hashing function
385
386 out = find(db.featuredb_hash == clip.id);
387 if isempty(out)
388 out = 0;
389 end
390 end
391
392 function out = get_next_pos(db)
393 % return index for the new clip features
394
395 out = numel(db.featuredb_hash) + 1;
396 end
397
398 function last_pos = get_last_pos(db)
399 % return index the last valid db entry
400
401 last_pos = find(db.featuredb_hash > 0, 1, 'last');
402 end
403
404
405 function set_pos(db, pos, clip)
406 % set index for the new clip features
407
408 db.featuredb_hash(pos) = clip.id;
409 end
410
411 function clear_pos(db, clip)
412 % remove index of the clip features
413
414 db.featuredb_hash(get_clip_pos(db, clip)) = 0;
415 end
416 end
417
418 methods (Static)
419
420 % ---
421 % this resets all feature dbs except the one exluded in the
422 % 'exclude', {''} cell
423 % ---
424 function reset_feature_dbs(varargin)
425
426 [exclude] = process_options(varargin,'exclude',{});
427 % ---
428 % resets all feature dbs except raw features
429 % ---
430 vars = whos ('*','global','-regexp', '^db_*');
431
432 % ---
433 % check if each is class of DBgen.
434 % if not in exclude variable, reset
435 % ---
436 for i = 1:numel(vars)
437
438 % import global variable
439 eval(sprintf('global %s',vars(i).name));
440
441 if strcmp(eval(sprintf('class(%s)',vars(i).name)), 'MTTAudioFeatureDBgen') ...
442 && isempty(strcellfind(exclude, vars(i).name))
443
444 eval(sprintf('%s.reset',vars(i).name));
445 end
446 end
447 end
448
449 function feature_type = import_type(matfile)
450 % function feature_type = import_type(matfile)
451 %
452 % returns the type of the saved feature db.
453
454 load(matfile, 'feature_type', '-MAT');
455 end
456
457 function db_nameo = db_name(type)
458 % returns the standard global var name for a db of given type
459
460 switch type
461 case 'MTTAudioFeatureRAW'
462 db_nameo = 'db_magnaaudiofeat';
463
464 case 'MTTAudioFeatureBasicSm'
465 db_nameo = 'db_magnaaudiofeat_basicsm';
466
467 case 'MTTTagFeatureGenreBasic'
468 db_nameo = 'db_magnatagfeat_genrebasic';
469
470 case 'MTTMixedFeatureGenreBasicSm'
471 db_nameo = 'db_magnamixedfeat_genrebasicsm';
472
473 otherwise
474 db_nameo = sprintf('db_%s', type);
475 end
476 end
477
478 function matfile = get_db_filename(featuretype, fparams,clips)
479 % get the paramhash
480 paramhash = MTTAudioFeatureDBgen.param_hash(featuretype, fparams);
481
482 % add the clip hash bit
483 cliphash = MTTAudioFeatureDBgen.clip_hash(clips);
484
485 % determine the filename
486 matfile = sprintf('f%s.%s.mat', paramhash,cliphash);
487 end
488
489 function ph = param_hash(type, varargin)
490 % loads the params for a feature type and adds the
491 % given parameter values to it.
492
493 % this function can be static or dynamic
494 if nargin > 1
495 % static case
496 dummy = feval(type,[], varargin{:});
497 else
498 % dynamic case
499 dummy = type;
500 end
501 ph = hash(xml_format(dummy.my_params),'MD5');
502 end
503
504 function ch = clip_hash(clips)
505
506 % returns the hash of a number of clips
507 ch = hash([class(clips(1)) mat2str(sort(clips.id))],'MD5');
508 end
509 end
510 end
511
512
513
514