wolffd@0
|
1 % ---
|
wolffd@0
|
2 % Mother of allMTT Audio Features
|
wolffd@0
|
3 % ---
|
wolffd@0
|
4
|
wolffd@0
|
5 classdef MTTAudioFeature < handle
|
wolffd@0
|
6
|
wolffd@0
|
7 % common properties
|
wolffd@0
|
8 properties (Dependent)
|
wolffd@0
|
9
|
wolffd@0
|
10 data;
|
wolffd@0
|
11 end
|
wolffd@0
|
12
|
wolffd@0
|
13 properties (Hidden)
|
wolffd@0
|
14
|
wolffd@0
|
15 % ---
|
wolffd@0
|
16 % TODO: get clip features by id and not by pos
|
wolffd@0
|
17 % ---
|
wolffd@0
|
18
|
wolffd@0
|
19 % position in db
|
wolffd@0
|
20 db_pos;
|
wolffd@0
|
21 end
|
wolffd@0
|
22
|
wolffd@0
|
23 % do not save whole db into mat file
|
wolffd@0
|
24 properties (Hidden, Transient)
|
wolffd@0
|
25
|
wolffd@0
|
26 % database
|
wolffd@0
|
27 my_db;
|
wolffd@0
|
28 end
|
wolffd@0
|
29
|
wolffd@0
|
30
|
wolffd@0
|
31 % common methods
|
wolffd@0
|
32 methods
|
wolffd@0
|
33
|
wolffd@0
|
34 % ---
|
wolffd@0
|
35 % constructor: pointer to feature in database
|
wolffd@0
|
36 % ---
|
wolffd@0
|
37 function feature = MTTAudioFeature(db, varargin)
|
wolffd@0
|
38 % feature = MTTAudioFeatureBasicSm(db, varargin)
|
wolffd@0
|
39
|
wolffd@0
|
40 if nargin >= 1
|
wolffd@0
|
41 % save database handle;
|
wolffd@0
|
42 feature.my_db = db;
|
wolffd@0
|
43
|
wolffd@0
|
44 if nargin >= 2
|
wolffd@0
|
45 if isnumeric(varargin{1})
|
wolffd@0
|
46
|
wolffd@0
|
47 feature.db_pos = varargin{1};
|
wolffd@0
|
48
|
wolffd@0
|
49 % ---
|
wolffd@0
|
50 % read parameters from data, which should not be
|
wolffd@0
|
51 % overwritten by the manual imputs ?
|
wolffd@0
|
52 % ---
|
wolffd@0
|
53 feature.set_params(feature.data.info.params);
|
wolffd@0
|
54
|
wolffd@0
|
55 if numel(varargin) > 1
|
wolffd@0
|
56 warning('Specified parameters cant be applied with preexisting data');
|
wolffd@0
|
57 end
|
wolffd@0
|
58
|
wolffd@0
|
59 else
|
wolffd@0
|
60
|
wolffd@0
|
61 % set parameters for feature extraction
|
wolffd@0
|
62 feature.set_params(varargin{:});
|
wolffd@0
|
63 end
|
wolffd@0
|
64 end
|
wolffd@0
|
65
|
wolffd@0
|
66 else
|
wolffd@0
|
67 % ---
|
wolffd@0
|
68 % TODO: empty constructor
|
wolffd@0
|
69 % ---
|
wolffd@0
|
70 end
|
wolffd@0
|
71 end
|
wolffd@0
|
72
|
wolffd@0
|
73 % ---
|
wolffd@0
|
74 % get and set methods, as the lazy matlab referencing
|
wolffd@0
|
75 % is of no use when the feature has to be adjusted
|
wolffd@0
|
76 % during the progess of finalising
|
wolffd@0
|
77 % ---
|
wolffd@0
|
78 function data = get.data(feature)
|
wolffd@0
|
79
|
wolffd@0
|
80 data = feature.my_db.featuredb(feature.db_pos);
|
wolffd@0
|
81 end
|
wolffd@0
|
82
|
wolffd@0
|
83 function set.data(feature, data)
|
wolffd@0
|
84
|
wolffd@0
|
85 feature.my_db.featuredb(feature.db_pos) = data;
|
wolffd@0
|
86 end
|
wolffd@0
|
87
|
wolffd@0
|
88 function id = owner_id(feature)
|
wolffd@0
|
89 % returns associated clip(s)
|
wolffd@0
|
90
|
wolffd@0
|
91 for i = 1:numel(feature)
|
wolffd@0
|
92 id(i) = feature(i).data.info.owner_id;
|
wolffd@0
|
93 end
|
wolffd@0
|
94 end
|
wolffd@0
|
95
|
wolffd@0
|
96 function out = dim(feature)
|
wolffd@0
|
97 % returns dimension of single feature vector
|
wolffd@0
|
98
|
wolffd@0
|
99 out = feature(1).data.final.dim;
|
wolffd@0
|
100 end
|
wolffd@0
|
101
|
wolffd@0
|
102 function label = labels(features)
|
wolffd@0
|
103 label = [];
|
wolffd@0
|
104 if isfield(features(1).data.final, 'vector_info')
|
wolffd@0
|
105
|
wolffd@0
|
106 % ---
|
wolffd@0
|
107 % TODO: these labels should be stored at a central point,
|
wolffd@0
|
108 % as this is a big waste of memory
|
wolffd@0
|
109 % ---
|
wolffd@0
|
110 label = features(1).data.final.vector_info.labels;
|
wolffd@0
|
111 end
|
wolffd@0
|
112 end
|
wolffd@0
|
113
|
wolffd@0
|
114 function out = vector(features)
|
wolffd@0
|
115 % returns the feature vector(s)
|
wolffd@0
|
116 % if multiple features are input, the vectors are
|
wolffd@0
|
117 % concatenated to a single matrix of size
|
wolffd@0
|
118 % (feature.dim x numel(features)
|
wolffd@0
|
119
|
wolffd@0
|
120 % finalise features if not done yet
|
wolffd@0
|
121 if ~isfield(features(1).data, 'final') || features(1).data.final.dim == 0
|
wolffd@0
|
122
|
wolffd@0
|
123 features.finalise();
|
wolffd@0
|
124 end
|
wolffd@0
|
125
|
wolffd@0
|
126 %shortcut for empty features
|
wolffd@0
|
127 if features(1).data.final.dim < 1
|
wolffd@0
|
128 out =[];
|
wolffd@0
|
129 return
|
wolffd@0
|
130 end
|
wolffd@0
|
131
|
wolffd@0
|
132 out = zeros(features(1).data.final.dim, numel(features));
|
wolffd@0
|
133 for i = 1:numel(features)
|
wolffd@0
|
134
|
wolffd@0
|
135 % finalise single feature vectors
|
wolffd@0
|
136 if ~isfield(features(i).data, 'final') || features(i).data.final.dim == 0
|
wolffd@0
|
137
|
wolffd@0
|
138 features(i).finalise();
|
wolffd@0
|
139 end
|
wolffd@0
|
140
|
wolffd@0
|
141 out(:,i) = features(i).data.final.vector;
|
wolffd@0
|
142 end
|
wolffd@0
|
143 end
|
wolffd@0
|
144
|
wolffd@0
|
145 function out = common(feature)
|
wolffd@0
|
146 % returns common feature values and params
|
wolffd@0
|
147
|
wolffd@0
|
148 out = feature(1).my_db.commondb;
|
wolffd@0
|
149 end
|
wolffd@0
|
150
|
wolffd@0
|
151 % visualises all the finalised feature vectors at once
|
wolffd@0
|
152 function a1 = visualise_vectors(features)
|
wolffd@0
|
153
|
wolffd@0
|
154 % Collect source description data
|
wolffd@0
|
155 ids = zeros( numel( features, 1));
|
wolffd@0
|
156
|
wolffd@0
|
157 for i = 1: numel(features)
|
wolffd@0
|
158
|
wolffd@0
|
159 ids(i) = features(i).owner_id();
|
wolffd@0
|
160 end
|
wolffd@0
|
161 % clips = MTTClip(ids);
|
wolffd@0
|
162
|
wolffd@0
|
163 % get collective feature data
|
wolffd@0
|
164 vec = features.vector();
|
wolffd@0
|
165
|
wolffd@0
|
166 % feature description data
|
wolffd@0
|
167 labels = features(1).labels;
|
wolffd@0
|
168
|
wolffd@0
|
169 % plot data
|
wolffd@0
|
170 h = figure;
|
wolffd@0
|
171 imagesc(vec);
|
wolffd@0
|
172 a1 = gca();
|
wolffd@0
|
173 axis xy;
|
wolffd@0
|
174
|
wolffd@0
|
175 set(a1,'XTick',1:numel(features), 'XTickLabel', ids);
|
wolffd@0
|
176
|
wolffd@0
|
177 if ~isempty(labels)
|
wolffd@0
|
178 set(a1,'YTick', [1:features(1).data.final.dim], 'YTickLabel', labels);
|
wolffd@0
|
179 end
|
wolffd@0
|
180
|
wolffd@0
|
181 xlabel('Clip ID');
|
wolffd@0
|
182 end
|
wolffd@0
|
183
|
wolffd@0
|
184
|
wolffd@0
|
185 % ---
|
wolffd@0
|
186 % compares the params of the feature with the
|
wolffd@0
|
187 % provided param struct or feature
|
wolffd@0
|
188 % ---
|
wolffd@0
|
189 function out = eq_params(this, in)
|
wolffd@0
|
190 % function out = eq_params(this, in)
|
wolffd@0
|
191 %
|
wolffd@0
|
192 % resolves if a feature with params(in) would be
|
wolffd@0
|
193 % the same as the given feature
|
wolffd@0
|
194
|
wolffd@0
|
195 type = this.my_db.featuredb_type;
|
wolffd@0
|
196
|
wolffd@0
|
197 % ---
|
wolffd@0
|
198 % construct dummy feature to get the params parsing right
|
wolffd@0
|
199 % ---
|
wolffd@0
|
200 if isstruct(in)
|
wolffd@0
|
201
|
wolffd@0
|
202 % call constructor for this feature
|
wolffd@0
|
203 % type without valid db
|
wolffd@0
|
204 in = feval(type, 0, in);
|
wolffd@0
|
205 end
|
wolffd@0
|
206
|
wolffd@0
|
207 % return whether the strings are equal or not
|
wolffd@0
|
208 out = strcmp(this.param_hash(), in.param_hash());
|
wolffd@0
|
209 end
|
wolffd@0
|
210
|
wolffd@0
|
211 function unused = set_params(this, varargin)
|
wolffd@0
|
212 % copies the parameters within the struct to the featrue instance,
|
wolffd@0
|
213 % or
|
wolffd@0
|
214 % uses the process_options function to set the parameters.
|
wolffd@0
|
215 % this is used for initialisation / constructor of features
|
wolffd@0
|
216
|
wolffd@0
|
217 unused = {};
|
wolffd@0
|
218 if numel(this) > 1
|
wolffd@0
|
219
|
wolffd@0
|
220 for i = 1:numel(this)
|
wolffd@0
|
221 set_params(this(i), varargin{:});
|
wolffd@0
|
222 end
|
wolffd@0
|
223 else
|
wolffd@0
|
224
|
wolffd@0
|
225 if isstruct(varargin{1})
|
wolffd@0
|
226
|
wolffd@0
|
227 % ok, just copy the information
|
wolffd@0
|
228 % this.my_params = varargin{1};
|
wolffd@0
|
229
|
wolffd@0
|
230 % ---
|
wolffd@0
|
231 % NOTE: this is a compability script
|
wolffd@0
|
232 % set fields succesively to keep new / nonset field names
|
wolffd@0
|
233 % we do not add parameters!!
|
wolffd@0
|
234 % ---
|
wolffd@0
|
235 fields = fieldnames(varargin{1});
|
wolffd@0
|
236 for i = 1:numel(fields)
|
wolffd@0
|
237
|
wolffd@0
|
238 % test whether the parameter is supported
|
wolffd@0
|
239 if isfield(this.my_params, fields{i})
|
wolffd@0
|
240
|
wolffd@0
|
241 this.my_params.(fields{i}) = varargin{1}.(fields{i});
|
wolffd@0
|
242 end
|
wolffd@0
|
243 end
|
wolffd@0
|
244 else
|
wolffd@0
|
245
|
wolffd@0
|
246 % get all parameter lines
|
wolffd@0
|
247 fields = fieldnames(this.my_params);
|
wolffd@0
|
248
|
wolffd@0
|
249 outputstring = '';
|
wolffd@0
|
250 inputstring = '';
|
wolffd@0
|
251
|
wolffd@0
|
252 % we collect the string for all the fields
|
wolffd@0
|
253 for i = 1:numel(fields)
|
wolffd@0
|
254
|
wolffd@0
|
255 % generate left- hand side of param collection
|
wolffd@0
|
256 outputstring = sprintf('%s this.my_params.%s',...
|
wolffd@0
|
257 outputstring, fields{i});
|
wolffd@0
|
258
|
wolffd@0
|
259 % right-hand-side
|
wolffd@0
|
260 inputstring = sprintf('%s ''%s'', this.my_params.%s',...
|
wolffd@0
|
261 inputstring, fields{i}, fields{i});
|
wolffd@0
|
262
|
wolffd@0
|
263 if i < numel(fields)
|
wolffd@0
|
264
|
wolffd@0
|
265 % put comma behind last argument
|
wolffd@0
|
266 inputstring = sprintf('%s,',inputstring);
|
wolffd@0
|
267 outputstring = sprintf('%s,',outputstring);
|
wolffd@0
|
268 end
|
wolffd@0
|
269
|
wolffd@0
|
270 end
|
wolffd@0
|
271
|
wolffd@0
|
272 % evaluate set
|
wolffd@0
|
273 eval(sprintf('[%s, unused] = process_options(varargin, %s);', ...
|
wolffd@0
|
274 outputstring, inputstring));
|
wolffd@0
|
275 end
|
wolffd@0
|
276 end
|
wolffd@0
|
277 end %fun
|
wolffd@0
|
278
|
wolffd@0
|
279 % ---
|
wolffd@0
|
280 % saveto function
|
wolffd@0
|
281 % ---
|
wolffd@0
|
282 function saveto(features, matfile)
|
wolffd@0
|
283 % saves (multiple features to a .mat file)
|
wolffd@0
|
284
|
wolffd@0
|
285 % get clip ids
|
wolffd@0
|
286 c = zeros(numel(features), 1);
|
wolffd@0
|
287 for i = 1:numel(features)
|
wolffd@0
|
288 c(i) = features(i).owner_id();
|
wolffd@0
|
289 end
|
wolffd@0
|
290
|
wolffd@0
|
291 % build clips
|
wolffd@0
|
292 clips = MTTClip(c);
|
wolffd@0
|
293
|
wolffd@0
|
294 % let db export the corresponding clips
|
wolffd@0
|
295 features(1).my_db.export(matfile, clips);
|
wolffd@0
|
296 end
|
wolffd@0
|
297
|
wolffd@0
|
298 % ---
|
wolffd@0
|
299 % destructor: do we really want to remove this
|
wolffd@0
|
300 % from the database? No, but
|
wolffd@0
|
301 % TODO: create marker for unused objects in db, and a cleanup
|
wolffd@0
|
302 % function
|
wolffd@0
|
303 % ---
|
wolffd@0
|
304 function delete(feature)
|
wolffd@0
|
305
|
wolffd@0
|
306 end
|
wolffd@0
|
307 end
|
wolffd@0
|
308
|
wolffd@0
|
309 methods (Hidden = true)
|
wolffd@0
|
310
|
wolffd@0
|
311 function assign(feature, db_pos)
|
wolffd@0
|
312 % sets the feature data link
|
wolffd@0
|
313
|
wolffd@0
|
314 feature.db_pos = db_pos;
|
wolffd@0
|
315 end
|
wolffd@0
|
316 end
|
wolffd@0
|
317
|
wolffd@0
|
318 methods (Static)
|
wolffd@0
|
319
|
wolffd@0
|
320 function ph = param_hash(type, varargin)
|
wolffd@0
|
321 % loads the params for a feature type and adds the
|
wolffd@0
|
322 % given parameter values to it.
|
wolffd@0
|
323
|
wolffd@0
|
324 % this function can be static or dynamic
|
wolffd@0
|
325 if nargin > 1
|
wolffd@0
|
326 % static case
|
wolffd@0
|
327 dummy = feval(type,[], varargin{:});
|
wolffd@0
|
328 else
|
wolffd@0
|
329 % dynamic case
|
wolffd@0
|
330 dummy = type;
|
wolffd@0
|
331 end
|
wolffd@0
|
332 ph = hash(xml_format(dummy.my_params),'MD5');
|
wolffd@0
|
333 end
|
wolffd@0
|
334
|
wolffd@0
|
335 function params = inherited_params(type, varargin)
|
wolffd@0
|
336 % loads the params for a feature type and adds the
|
wolffd@0
|
337 % given parameter values to it.
|
wolffd@0
|
338
|
wolffd@0
|
339 dummy = feval(type);
|
wolffd@0
|
340
|
wolffd@0
|
341 params = dummy.my_params;
|
wolffd@0
|
342
|
wolffd@0
|
343 % basic check if the input is correct
|
wolffd@0
|
344 if mod(numel(varargin), 2) ~= 0
|
wolffd@0
|
345 error('number of params does not match number of values');
|
wolffd@0
|
346 end
|
wolffd@0
|
347
|
wolffd@0
|
348 % add the fields to the struct
|
wolffd@0
|
349 for i = 1:2:(numel(varargin)-1);
|
wolffd@0
|
350
|
wolffd@0
|
351 params.(varargin{i}) = varargin{i+1};
|
wolffd@0
|
352 end
|
wolffd@0
|
353 end
|
wolffd@0
|
354 end
|
wolffd@0
|
355 end
|
wolffd@0
|
356
|
wolffd@0
|
357
|
wolffd@0
|
358
|
wolffd@0
|
359
|
wolffd@0
|
360
|
wolffd@0
|
361
|
wolffd@0
|
362 |