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