comparison core/magnatagatune/MTTMixedFeatureStober11.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 MTTMixedFeatureStober11 < MTTAudioFeature & handle
2 % ---
3 % This Class contains
4 % features are extracted
5 % as described in Slaney 08 - LEARNING A METRIC FOR MUSIC SIMILARITY
6 %
7 % The usual workflow for these features constist of three steps
8 % 1. extract: extracts the basic single-file dependent features
9 % 2. define_global_transform: calculates the global feature
10 % transformation parameters
11 % 3. finalise: applies the common transformations to a specific feature
12 % ---
13
14 properties(Constant = true)
15
16 % svn hook
17 my_revision = str2double(substr('$Rev$', 5, -1));
18 end
19
20 properties
21 % ---
22 % Set default parameters
23 % ---
24 my_params = struct(...
25 'stob_lowaudio', 1, ...
26 'stob_highaudio', 1, ... %
27 'stob_tags', 1, ... %
28 'stob_norm', 1 ...
29 );
30 end
31
32 % ---
33 % member functions
34 % ---
35 methods
36
37 % ---
38 % constructor: pointer to feature in database
39 % ---
40 function feature = MTTMixedFeatureStober11(varargin)
41
42 feature = feature@MTTAudioFeature(varargin{:});
43
44 end
45 % ---
46 % extract feature data from raw audio features
47 % ---
48 function data = extract(feature, clip)
49 % ---
50 % get features. this includes possible
51 % local normalisations
52 % ---
53
54 global globalvars;
55 global stobbase;
56
57 if isempty(stobbase);
58 stobbase = load('features_stober');
59 end
60
61 % ---
62 % NOTE: we define feature sets which are included /
63 % excluded according to the specified parameters
64 % ---
65
66 lowAudio = {'pitchMean', 'pitchSdev', 'timbreMean', 'timbreSdev'};
67
68 % highAudio features more or less correspond to slaney 08 features
69 hiAudio = {'energy','key','loudness','timeSignature',...
70 'danceability', 'mode', 'tempo'};
71
72 metadat = {'tags'};
73
74 allowedFeat = {};
75
76 % Select the features to keep
77 if feature(1).my_params.stob_lowaudio
78 allowedFeat = {allowedFeat{:}, lowAudio{:}};
79 end
80 if feature(1).my_params.stob_highaudio
81 allowedFeat = {allowedFeat{:}, hiAudio{:}};
82 end
83 if feature(1).my_params.stob_tags
84 allowedFeat = {allowedFeat{:}, metadat{:}};
85 end
86
87 % get the actual clip id
88 idx = find(stobbase.clipIds == clip.id);
89
90 % ---
91 % NOTE: we just copy everything in a big matrix and then
92 % normalise the data later
93 % ---
94 data.vector_info = {};
95 data.stobraw = [];
96 fields = fieldnames(stobbase);
97 for i = 1:numel(fields)
98
99 % skip clip ID field
100 if strcmp(fields{i},'clipIds');
101 continue;
102 end
103
104 % skip unwanted features
105 if isempty(strcellfind(allowedFeat, fields{i}))
106 continue;
107 end
108
109 % ---
110 % TODO: special case for tag features, including
111 % the tag names
112 % ---
113
114 % put field info into right position
115 data.vector_info{numel(data.stobraw)+1} = fields{i};
116
117 % add data to feature
118 if size(stobbase.(fields{i}),1) == 1
119 data.stobraw(end+1) = stobbase.(fields{i})(idx);
120 else
121 % concatenate vector
122 tmpdat = stobbase.(fields{i})(idx,:);
123 data.stobraw(end+1:end+numel(tmpdat)) = tmpdat;
124 end
125 end
126 % padd further info struct
127 data.vector_info(end+1:numel(data.stobraw)) =...
128 cell(numel(data.stobraw) - numel(data.vector_info) , 1);
129
130 % ---
131 % prepare field for final features
132 % ---
133 data.final.vector = [];
134 data.final.vector_info = struct();
135 data.final.dim = 0;
136
137 % save info data
138 data.info.type = 'MTTMixedFeatureStober11';
139 data.info.owner_id = clip.id;
140 data.info.creatorrev = feature.my_revision;
141
142 % save parameters
143 data.info.params = feature.my_params;
144 end
145
146 function define_global_transform(features)
147 % calculate and set normalization factors from the group of
148 % input features. These features will be set for the full database
149
150 final = zeros(numel(features(1).data.stobraw), numel(features));
151 for i = 1:numel(features)
152 if ~isempty(features(i).data.stobraw)
153 final(:,i) = features(i).data.stobraw';
154 end
155 end
156
157 if features(1).my_params.stob_norm
158 if numel(features) == 1
159 error ('Insert feature array for this method, or set normalisation to 0');
160 end
161
162 % ---
163 % here, we only need to define the post-normalisation
164 % ---
165 [final, pstd] = mapminmax(final,0,1);
166 common.stobstats.post_norm = pstd;
167
168 % ---
169 % NOTE: whitening as in slaney??
170 % Would make reading the
171 % mahal matrices really hard
172 % ---
173
174 features(1).my_db.set_common(common);
175
176 else
177
178 features(1).my_db.set_common([1]);
179 end
180
181 % save the normalised features straight away!
182 features.finalise(final);
183 end
184
185
186 function finalise(features, final)
187 % applies a final transformation and
188 % collects the information of this feature within a single vector
189 % see info for types in specific dimensions
190 % check if features have been finalised already
191
192 % ---
193 % set feature labelling
194 % ---
195
196 info = {};
197
198 % ---
199 % construct resulting feature vector out of features
200 % ---
201 if nargin == 2 && isempty(final)
202
203 % the final vector etc already are set to zero;
204 return;
205
206 elseif nargin == 2 && (numel(features) == size(final, 2))
207 % the features have already been preassembled
208
209 for i = 1:numel(features)
210
211 % check for neccesary parameters
212 if isempty(features(i).my_db.commondb)
213
214 error('Define the global transformation first')
215 return;
216 end
217
218 features(i).data.final.vector = final(:,i);
219 features(i).data.final.dim = size(final,1);
220
221 % fill up info struct and append to feature
222 features(i).data.final.vector_info.labels = ...
223 features(i).data.vector_info;
224 end
225 else
226 % ---
227 % if features have been added after gettin gnormalisation
228 % parameters, ther should be still an option to include
229 % them
230 % ---
231
232 for i = 1:numel(features)
233
234 % check for neccesary parameters
235 if isempty(features(i).my_db.commondb)
236
237 error('Define the global transformation first')
238 return;
239 end
240
241 final = features(i).data.stobraw';
242
243 if features(1).my_params.stob_norm == 1
244
245 [final] = mapminmax('apply', final, features(1).common.stobstats.post_norm);
246 end
247
248 features(i).data.final.vector = final;
249 features(i).data.final.dim = size(final,1);
250
251 % fill up info struct and append to feature
252 features(i).data.final.vector_info.labels = ...
253 features(i).data.vector_info;
254 end
255
256 end
257
258 % ---
259 % TODO: Maybe delete more basic features again at this point?
260 % ---
261 end
262
263 % ---
264 % destructor: do we really want to remove this
265 % from the database? No, but
266 % TODO: create marker for unused objects in db, and a cleanup
267 % function
268 % ---
269 function delete(feature)
270
271 end
272 end
273 end