wolffd@0: % --- wolffd@0: % Mother of allMTT Audio Features wolffd@0: % --- wolffd@0: wolffd@0: classdef MTTAudioFeature < handle wolffd@0: wolffd@0: % common properties wolffd@0: properties (Dependent) wolffd@0: wolffd@0: data; wolffd@0: end wolffd@0: wolffd@0: properties (Hidden) wolffd@0: wolffd@0: % --- wolffd@0: % TODO: get clip features by id and not by pos wolffd@0: % --- wolffd@0: wolffd@0: % position in db wolffd@0: db_pos; wolffd@0: end wolffd@0: wolffd@0: % do not save whole db into mat file wolffd@0: properties (Hidden, Transient) wolffd@0: wolffd@0: % database wolffd@0: my_db; wolffd@0: end wolffd@0: wolffd@0: wolffd@0: % common methods wolffd@0: methods wolffd@0: wolffd@0: % --- wolffd@0: % constructor: pointer to feature in database wolffd@0: % --- wolffd@0: function feature = MTTAudioFeature(db, varargin) wolffd@0: % feature = MTTAudioFeatureBasicSm(db, varargin) wolffd@0: wolffd@0: if nargin >= 1 wolffd@0: % save database handle; wolffd@0: feature.my_db = db; wolffd@0: wolffd@0: if nargin >= 2 wolffd@0: if isnumeric(varargin{1}) wolffd@0: wolffd@0: feature.db_pos = varargin{1}; wolffd@0: wolffd@0: % --- wolffd@0: % read parameters from data, which should not be wolffd@0: % overwritten by the manual imputs ? wolffd@0: % --- wolffd@0: feature.set_params(feature.data.info.params); wolffd@0: wolffd@0: if numel(varargin) > 1 wolffd@0: warning('Specified parameters cant be applied with preexisting data'); wolffd@0: end wolffd@0: wolffd@0: else wolffd@0: wolffd@0: % set parameters for feature extraction wolffd@0: feature.set_params(varargin{:}); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: else wolffd@0: % --- wolffd@0: % TODO: empty constructor wolffd@0: % --- wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: % --- wolffd@0: % get and set methods, as the lazy matlab referencing wolffd@0: % is of no use when the feature has to be adjusted wolffd@0: % during the progess of finalising wolffd@0: % --- wolffd@0: function data = get.data(feature) wolffd@0: wolffd@0: data = feature.my_db.featuredb(feature.db_pos); wolffd@0: end wolffd@0: wolffd@0: function set.data(feature, data) wolffd@0: wolffd@0: feature.my_db.featuredb(feature.db_pos) = data; wolffd@0: end wolffd@0: wolffd@0: function id = owner_id(feature) wolffd@0: % returns associated clip(s) wolffd@0: wolffd@0: for i = 1:numel(feature) wolffd@0: id(i) = feature(i).data.info.owner_id; wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: function out = dim(feature) wolffd@0: % returns dimension of single feature vector wolffd@0: wolffd@0: out = feature(1).data.final.dim; wolffd@0: end wolffd@0: wolffd@0: function label = labels(features) wolffd@0: label = []; wolffd@0: if isfield(features(1).data.final, 'vector_info') wolffd@0: wolffd@0: % --- wolffd@0: % TODO: these labels should be stored at a central point, wolffd@0: % as this is a big waste of memory wolffd@0: % --- wolffd@0: label = features(1).data.final.vector_info.labels; wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: function out = vector(features) wolffd@0: % returns the feature vector(s) wolffd@0: % if multiple features are input, the vectors are wolffd@0: % concatenated to a single matrix of size wolffd@0: % (feature.dim x numel(features) wolffd@0: wolffd@0: % finalise features if not done yet wolffd@0: if ~isfield(features(1).data, 'final') || features(1).data.final.dim == 0 wolffd@0: wolffd@0: features.finalise(); wolffd@0: end wolffd@0: wolffd@0: %shortcut for empty features wolffd@0: if features(1).data.final.dim < 1 wolffd@0: out =[]; wolffd@0: return wolffd@0: end wolffd@0: wolffd@0: out = zeros(features(1).data.final.dim, numel(features)); wolffd@0: for i = 1:numel(features) wolffd@0: wolffd@0: % finalise single feature vectors wolffd@0: if ~isfield(features(i).data, 'final') || features(i).data.final.dim == 0 wolffd@0: wolffd@0: features(i).finalise(); wolffd@0: end wolffd@0: wolffd@0: out(:,i) = features(i).data.final.vector; wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: function out = common(feature) wolffd@0: % returns common feature values and params wolffd@0: wolffd@0: out = feature(1).my_db.commondb; wolffd@0: end wolffd@0: wolffd@0: % visualises all the finalised feature vectors at once wolffd@0: function a1 = visualise_vectors(features) wolffd@0: wolffd@0: % Collect source description data wolffd@0: ids = zeros( numel( features, 1)); wolffd@0: wolffd@0: for i = 1: numel(features) wolffd@0: wolffd@0: ids(i) = features(i).owner_id(); wolffd@0: end wolffd@0: % clips = MTTClip(ids); wolffd@0: wolffd@0: % get collective feature data wolffd@0: vec = features.vector(); wolffd@0: wolffd@0: % feature description data wolffd@0: labels = features(1).labels; wolffd@0: wolffd@0: % plot data wolffd@0: h = figure; wolffd@0: imagesc(vec); wolffd@0: a1 = gca(); wolffd@0: axis xy; wolffd@0: wolffd@0: set(a1,'XTick',1:numel(features), 'XTickLabel', ids); wolffd@0: wolffd@0: if ~isempty(labels) wolffd@0: set(a1,'YTick', [1:features(1).data.final.dim], 'YTickLabel', labels); wolffd@0: end wolffd@0: wolffd@0: xlabel('Clip ID'); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: % --- wolffd@0: % compares the params of the feature with the wolffd@0: % provided param struct or feature wolffd@0: % --- wolffd@0: function out = eq_params(this, in) wolffd@0: % function out = eq_params(this, in) wolffd@0: % wolffd@0: % resolves if a feature with params(in) would be wolffd@0: % the same as the given feature wolffd@0: wolffd@0: type = this.my_db.featuredb_type; wolffd@0: wolffd@0: % --- wolffd@0: % construct dummy feature to get the params parsing right wolffd@0: % --- wolffd@0: if isstruct(in) wolffd@0: wolffd@0: % call constructor for this feature wolffd@0: % type without valid db wolffd@0: in = feval(type, 0, in); wolffd@0: end wolffd@0: wolffd@0: % return whether the strings are equal or not wolffd@0: out = strcmp(this.param_hash(), in.param_hash()); wolffd@0: end wolffd@0: wolffd@0: function unused = set_params(this, varargin) wolffd@0: % copies the parameters within the struct to the featrue instance, wolffd@0: % or wolffd@0: % uses the process_options function to set the parameters. wolffd@0: % this is used for initialisation / constructor of features wolffd@0: wolffd@0: unused = {}; wolffd@0: if numel(this) > 1 wolffd@0: wolffd@0: for i = 1:numel(this) wolffd@0: set_params(this(i), varargin{:}); wolffd@0: end wolffd@0: else wolffd@0: wolffd@0: if isstruct(varargin{1}) wolffd@0: wolffd@0: % ok, just copy the information wolffd@0: % this.my_params = varargin{1}; wolffd@0: wolffd@0: % --- wolffd@0: % NOTE: this is a compability script wolffd@0: % set fields succesively to keep new / nonset field names wolffd@0: % we do not add parameters!! wolffd@0: % --- wolffd@0: fields = fieldnames(varargin{1}); wolffd@0: for i = 1:numel(fields) wolffd@0: wolffd@0: % test whether the parameter is supported wolffd@0: if isfield(this.my_params, fields{i}) wolffd@0: wolffd@0: this.my_params.(fields{i}) = varargin{1}.(fields{i}); wolffd@0: end wolffd@0: end wolffd@0: else wolffd@0: wolffd@0: % get all parameter lines wolffd@0: fields = fieldnames(this.my_params); wolffd@0: wolffd@0: outputstring = ''; wolffd@0: inputstring = ''; wolffd@0: wolffd@0: % we collect the string for all the fields wolffd@0: for i = 1:numel(fields) wolffd@0: wolffd@0: % generate left- hand side of param collection wolffd@0: outputstring = sprintf('%s this.my_params.%s',... wolffd@0: outputstring, fields{i}); wolffd@0: wolffd@0: % right-hand-side wolffd@0: inputstring = sprintf('%s ''%s'', this.my_params.%s',... wolffd@0: inputstring, fields{i}, fields{i}); wolffd@0: wolffd@0: if i < numel(fields) wolffd@0: wolffd@0: % put comma behind last argument wolffd@0: inputstring = sprintf('%s,',inputstring); wolffd@0: outputstring = sprintf('%s,',outputstring); wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: wolffd@0: % evaluate set wolffd@0: eval(sprintf('[%s, unused] = process_options(varargin, %s);', ... wolffd@0: outputstring, inputstring)); wolffd@0: end wolffd@0: end wolffd@0: end %fun wolffd@0: wolffd@0: % --- wolffd@0: % saveto function wolffd@0: % --- wolffd@0: function saveto(features, matfile) wolffd@0: % saves (multiple features to a .mat file) wolffd@0: wolffd@0: % get clip ids wolffd@0: c = zeros(numel(features), 1); wolffd@0: for i = 1:numel(features) wolffd@0: c(i) = features(i).owner_id(); wolffd@0: end wolffd@0: wolffd@0: % build clips wolffd@0: clips = MTTClip(c); wolffd@0: wolffd@0: % let db export the corresponding clips wolffd@0: features(1).my_db.export(matfile, clips); wolffd@0: end wolffd@0: wolffd@0: % --- wolffd@0: % destructor: do we really want to remove this wolffd@0: % from the database? No, but wolffd@0: % TODO: create marker for unused objects in db, and a cleanup wolffd@0: % function wolffd@0: % --- wolffd@0: function delete(feature) wolffd@0: wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: methods (Hidden = true) wolffd@0: wolffd@0: function assign(feature, db_pos) wolffd@0: % sets the feature data link wolffd@0: wolffd@0: feature.db_pos = db_pos; wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: methods (Static) wolffd@0: wolffd@0: function ph = param_hash(type, varargin) wolffd@0: % loads the params for a feature type and adds the wolffd@0: % given parameter values to it. wolffd@0: wolffd@0: % this function can be static or dynamic wolffd@0: if nargin > 1 wolffd@0: % static case wolffd@0: dummy = feval(type,[], varargin{:}); wolffd@0: else wolffd@0: % dynamic case wolffd@0: dummy = type; wolffd@0: end wolffd@0: ph = hash(xml_format(dummy.my_params),'MD5'); wolffd@0: end wolffd@0: wolffd@0: function params = inherited_params(type, varargin) wolffd@0: % loads the params for a feature type and adds the wolffd@0: % given parameter values to it. wolffd@0: wolffd@0: dummy = feval(type); wolffd@0: wolffd@0: params = dummy.my_params; wolffd@0: wolffd@0: % basic check if the input is correct wolffd@0: if mod(numel(varargin), 2) ~= 0 wolffd@0: error('number of params does not match number of values'); wolffd@0: end wolffd@0: wolffd@0: % add the fields to the struct wolffd@0: for i = 1:2:(numel(varargin)-1); wolffd@0: wolffd@0: params.(varargin{i}) = varargin{i+1}; wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: wolffd@0: wolffd@0: wolffd@0: wolffd@0: