Mercurial > hg > camir-aes2014
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 |