Mercurial > hg > camir-aes2014
view 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 |
line wrap: on
line source
classdef MTTMixedFeatureStober11 < MTTAudioFeature & handle % --- % This Class contains % features are extracted % as described in Slaney 08 - LEARNING A METRIC FOR MUSIC SIMILARITY % % The usual workflow for these features constist of three steps % 1. extract: extracts the basic single-file dependent features % 2. define_global_transform: calculates the global feature % transformation parameters % 3. finalise: applies the common transformations to a specific feature % --- properties(Constant = true) % svn hook my_revision = str2double(substr('$Rev$', 5, -1)); end properties % --- % Set default parameters % --- my_params = struct(... 'stob_lowaudio', 1, ... 'stob_highaudio', 1, ... % 'stob_tags', 1, ... % 'stob_norm', 1 ... ); end % --- % member functions % --- methods % --- % constructor: pointer to feature in database % --- function feature = MTTMixedFeatureStober11(varargin) feature = feature@MTTAudioFeature(varargin{:}); end % --- % extract feature data from raw audio features % --- function data = extract(feature, clip) % --- % get features. this includes possible % local normalisations % --- global globalvars; global stobbase; if isempty(stobbase); stobbase = load('features_stober'); end % --- % NOTE: we define feature sets which are included / % excluded according to the specified parameters % --- lowAudio = {'pitchMean', 'pitchSdev', 'timbreMean', 'timbreSdev'}; % highAudio features more or less correspond to slaney 08 features hiAudio = {'energy','key','loudness','timeSignature',... 'danceability', 'mode', 'tempo'}; metadat = {'tags'}; allowedFeat = {}; % Select the features to keep if feature(1).my_params.stob_lowaudio allowedFeat = {allowedFeat{:}, lowAudio{:}}; end if feature(1).my_params.stob_highaudio allowedFeat = {allowedFeat{:}, hiAudio{:}}; end if feature(1).my_params.stob_tags allowedFeat = {allowedFeat{:}, metadat{:}}; end % get the actual clip id idx = find(stobbase.clipIds == clip.id); % --- % NOTE: we just copy everything in a big matrix and then % normalise the data later % --- data.vector_info = {}; data.stobraw = []; fields = fieldnames(stobbase); for i = 1:numel(fields) % skip clip ID field if strcmp(fields{i},'clipIds'); continue; end % skip unwanted features if isempty(strcellfind(allowedFeat, fields{i})) continue; end % --- % TODO: special case for tag features, including % the tag names % --- % put field info into right position data.vector_info{numel(data.stobraw)+1} = fields{i}; % add data to feature if size(stobbase.(fields{i}),1) == 1 data.stobraw(end+1) = stobbase.(fields{i})(idx); else % concatenate vector tmpdat = stobbase.(fields{i})(idx,:); data.stobraw(end+1:end+numel(tmpdat)) = tmpdat; end end % padd further info struct data.vector_info(end+1:numel(data.stobraw)) =... cell(numel(data.stobraw) - numel(data.vector_info) , 1); % --- % prepare field for final features % --- data.final.vector = []; data.final.vector_info = struct(); data.final.dim = 0; % save info data data.info.type = 'MTTMixedFeatureStober11'; data.info.owner_id = clip.id; data.info.creatorrev = feature.my_revision; % save parameters data.info.params = feature.my_params; end function define_global_transform(features) % calculate and set normalization factors from the group of % input features. These features will be set for the full database final = zeros(numel(features(1).data.stobraw), numel(features)); for i = 1:numel(features) if ~isempty(features(i).data.stobraw) final(:,i) = features(i).data.stobraw'; end end if features(1).my_params.stob_norm if numel(features) == 1 error ('Insert feature array for this method, or set normalisation to 0'); end % --- % here, we only need to define the post-normalisation % --- [final, pstd] = mapminmax(final,0,1); common.stobstats.post_norm = pstd; % --- % NOTE: whitening as in slaney?? % Would make reading the % mahal matrices really hard % --- features(1).my_db.set_common(common); else features(1).my_db.set_common([1]); end % save the normalised features straight away! features.finalise(final); end function finalise(features, final) % applies a final transformation and % collects the information of this feature within a single vector % see info for types in specific dimensions % check if features have been finalised already % --- % set feature labelling % --- info = {}; % --- % construct resulting feature vector out of features % --- if nargin == 2 && isempty(final) % the final vector etc already are set to zero; return; elseif nargin == 2 && (numel(features) == size(final, 2)) % the features have already been preassembled for i = 1:numel(features) % check for neccesary parameters if isempty(features(i).my_db.commondb) error('Define the global transformation first') return; end features(i).data.final.vector = final(:,i); features(i).data.final.dim = size(final,1); % fill up info struct and append to feature features(i).data.final.vector_info.labels = ... features(i).data.vector_info; end else % --- % if features have been added after gettin gnormalisation % parameters, ther should be still an option to include % them % --- for i = 1:numel(features) % check for neccesary parameters if isempty(features(i).my_db.commondb) error('Define the global transformation first') return; end final = features(i).data.stobraw'; if features(1).my_params.stob_norm == 1 [final] = mapminmax('apply', final, features(1).common.stobstats.post_norm); end features(i).data.final.vector = final; features(i).data.final.dim = size(final,1); % fill up info struct and append to feature features(i).data.final.vector_info.labels = ... features(i).data.vector_info; end end % --- % TODO: Maybe delete more basic features again at this point? % --- end % --- % destructor: do we really want to remove this % from the database? No, but % TODO: create marker for unused objects in db, and a cleanup % function % --- function delete(feature) end end end