Skip to content
Snippets Groups Projects
Select Git revision
  • 7915bb98250899bed7e4e96cbfa38f487a063dfc
  • master default protected
  • develop protected
  • big_2017_api_change
  • VA_v2024a
  • VA_v2023b
  • VA_v2023a
  • before_VANet_update
  • VA_v2022a
  • before_cmake_rework
  • v2021.a
  • v2020.a
  • v2019.a
  • v2018.b
  • v2017.c
  • v2017.a
  • v2016.a
17 results

VAMatlabExecutable.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    itaSuper.m 45.16 KiB
    classdef itaSuper < itaMeta
        
        
        %ITASUPER - Mother of all ita data-object classes (itaAudio/itaResult)
        %   Detailed explanation goes here
        %
        %   Reference page in Help browser
        %   <a href="matlab:doc itaSuper">doc itaSuper</a>
        
        % <ITA-Toolbox>
        % This file is part of the ITA-Toolbox. Some rights reserved.
        % You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
        % </ITA-Toolbox>
        
        properties(Access = private, Hidden = true)
            % Internal fields, no access from outside the class
            mData = [];
            mDimensions = 0;
            mDomain = 'time';                % 'time' / 'freq'
            mChannelNames = {};
            mChannelUnits = {};
            mChannelCoordinates = itaCoordinates();
            mChannelOrientation = itaCoordinates();
            mChannelSensors = {};
            mChannelUserData = {};
            mAllowDBPlot = true;
            
            % up and view vector for hrtf data
            mObjectCoordinates = itaCoordinates();
            mObjectViewVector = itaCoordinates();
            mObjectUpVector = itaCoordinates();
            
            mDataType = 'double';           % Type for internal data
            mDataTypeOutput = 'double';     % Type used for output
            mDataTypeEqual = true;          % On/Off Switch for data type casts (speed reason)
            mDataFactor = 1;                % Factor for scaling if using int
        end
        
        properties(Constant, Hidden = true)
            % display options
            LINE_LENGTH  = 90;
        end
        
        %     properties(Abstract)
        %         % Properties that all sub-classes have but are not used in this class
        %         %freqVector
        %         %timeVector
        %     end
        
        properties(Dependent = true, Hidden = false)
            
            time %time domain data (get/set) - full dimensions
            timeData %time domain data in 2D
            
            freq %frequency domain data (get/set) - full dimensions
            freqData %frequency domain data in 2D
            
            
            nBins %number of frequency samples called bins
            nSamples % number of time samples
            
            domain % domain of data ('time'/'freq')
            dimensions % dimensions of the data field
            
            dataType %raw data type, data is stored in... (single/double)
            dataTypeOutput %data type when you access data (single/double), conversion
            
            channelNames %Names for each channel (cell string)
            channelUnits %Units for each channel (cell string)
            channelCoordinates %Coordinates for each channel (have to be itaCoordinates)
            channelOrientation %Orientation for each channel (have to be itaCoordinates)
            channelUserData %arbitrary userdata for each channel (cell array)
            
            allowDBPlot % Does a dB Plot make any sense ?
            
            objectCoordinates   % the coordinates of the measured object
            objectViewVector    % view direction of the measured object
            objectUpVector      % up vector of the measured object
        end
        properties(Dependent = true, Hidden = true)
            channelSensors %Sensor name for each channel (cell string)
            data %raw data, could be time or frequency domain (CAREFUL!)
            dataFactor %ask RSC?
        end
        methods
            
            function this = itaSuper(varargin)
                % Constructor
                % Calls:
                %   itaMeta() - Empty object
                %   itaMeta(n) or itaMeta([x y z]) - Preinitialize n*n or x*y*z objects
                %   itaMeta(itaMeta) - Copy-Constructor
                %   itaMeta(Struct) - convert/import struct
                %   itaMeta( ... ,n) or itaMeta(... , [a b c]) - Prinitialize with datafield size a*b*c
                
                %this = this@itaMeta(varargin);
                
                if nargin == 0
                    %Nothing to do
                elseif nargin >= 1
                    if isnumeric([varargin{:}]) % Preinitialize n-Instances
                        if any([varargin{:}] > 1)
                            this = repmat(this,[varargin{:}]);
                        end
                    end
                    if isa(varargin{1},mfilename) % Copy-Constructor
                        prop = properties(varargin{1});
                        % first tell domain and data, otherwise errors might occur
                        prop = [{'domain';'data'}; prop];              % 3.8.11 added data, mpo
                        % all domain specific data is not needed here
                        % TODO: Shift this somehow to itaAudio.m
                        try
                            prop{strcmp(prop,'dat')} = 'VOID';
                        catch %#ok<CTCH>
                            ita_verbose_info('constructor of itaSuper: skipping property dat');
                        end
                        try
                            prop{strcmp(prop,'spk')} = 'VOID';
                        catch %#ok<CTCH>
                            ita_verbose_info('constructor of itaSuper: skipping property spk');
                        end
                        prop{strcmp(prop,'time')} = 'VOID';
                        prop{strcmp(prop,'timeData')} = 'VOID';
                        prop{strcmp(prop,'freq')} = 'VOID';
                        prop{strcmp(prop,'freqData')} = 'VOID';
                        
                        for ind = 1:length(prop)
                            try
                                this.(prop{ind}) = varargin{1}.(prop{ind});
                            catch
                                ita_verbose_info(['constructor of itaSuper: ignoring property ' prop{ind}]);
                            end
                        end
                    end
                    if isstruct(varargin{1}) % Struct input/convert
                        fieldName = fieldnames(varargin{1});
                        preDataFields = {'domain', 'dataType', 'dataTypeOutput','mDataFactor','dataFactor'}; %RSC: Fields that must be set bevor data may be set
                        for idfn = 1:numel(preDataFields)
                            if find(strcmpi(fieldName,preDataFields{idfn})) > find(strcmpi(fieldName,'data'))
                                idx = find(strcmpi(fieldName,preDataFields{idfn}));
                                varargin{1} = orderfields(varargin{1},[idx,1:idx-1,idx+1:numel(fieldName)]);
                                fieldName = fieldnames(varargin{1});
                            end
                        end
                        for ind = 1:numel(fieldName)
                            try
                                this.(fieldName{ind}) = varargin{1}.(fieldName{ind});
                            catch errmsg
                                disp(errmsg);
                            end
                        end
                    end
                end
                if nargin == 2
                    for idx = 1:numel(this)
                        this(idx).mData = deal(nan(varargin{2})); %#ok<AGROW>
                    end
                end
            end
            
            
            %% Get/set Stuff
            function result = get.time(this)
                % output n-dimensions
                result = reshape(this.timeData, [this.nSamples this.dimensions]);
            end
            function this = set.time(this,value)
                dimensionsValue = size(value);
                this.timeData = reshape(value, dimensionsValue(1), []);
                this.dimensions = dimensionsValue(2:end);
            end
            function result = get.freq(this)
                % output n-dimensions
                result = reshape(this.freqData, [this.nBins this.dimensions]);
            end
            function this = set.freq(this,value)
                dimensionsValue = size(value);
                this.freqData = reshape(value, dimensionsValue(1), []);
                this.dimensions = dimensionsValue(2:end);
            end
            
            function result = get.timeData(this)
                this = ifft(this);
                result = this.data;
            end
            function this = set.timeData(this,value)
                this.domain = 'time';
                this.data = value;
            end
            function result = get.freqData(this)
                this = fft(this);
                result = this.data;
            end
            
            function this = set.freqData(this,value)
                this.domain = 'freq';
                this.data = value;
            end
            
            function result = get.data(this)
                result = get_data(this);
            end
            
            function this = set.data(this,value)
                sizeValue = size(value);
                
                if numel(sizeValue) > 2
                    error([upper(mfilename) '.set.data  only 2D-data is allowed, use .freq or .time for higher dimensions']);
                end
                
                % BMA: Vector can be given as columns or rows.
                %if sizeValue(1) == 1
                %    value = value(:); % RSC - there is a bug here a = itaResult; a.freq = zeros(1,3); leads to a result with 3 bins and 3 channels
                %end
                
                this = set_data(this, value);
                this.dateModified = datevec(now);
                
                if prod(this.dimensions) ~= sizeValue(2)
                    % only set the dimensions if there is inconsistent data
                    this.dimensions = sizeValue(2);
                end
            end
            
            function result = get.domain(this)
                result = this.mDomain;
            end
            function this = set.domain(this,value)
                % only do something if there is a change
                if strcmpi(this.domain, value)
                    return;
                end
                
                % the domain will be switched, data set to NaNs
                %             nChannels = this.nChannels;
                switch lower(value)
                    case 'time'
                        %                   this.data = nan(this.nSamples, nChannels);
                        this.mDomain = 'time';
                    case 'freq'
                        %                     nBins = this.nBins;
                        this.mDomain = 'freq';
                        %                    this.data = nan(nBins, nChannels) + 1i * nan(nBins, nChannels);
                    otherwise
                        error('%s:I don''t know this domain.',upper(mfilename))
                end
            end
            
            %% Channel Stuff
            function this = channelDelete(this, idxChDelete)
                % Example: oAudio = oAudio.channelDelete(1); %object has to be
                % set to itself again, since itaSuper is no handle class.
                validateattributes(idxChDelete,{'numeric'},{'vector','nonempty','integer'})
                if numel(this) > 1 
                    ita_verbose_info('This does not work for multiinstance itaAudio objects.',0);
                    return;
                end
                idxChToKeep              = 1:this.nChannels;
                idxChToKeep(idxChDelete) = [];
                this                     = this.ch(idxChToKeep);
            end
                
            function result = get.channelNames(this)
                result = this.mChannelNames;
                if numel(result) ~= this.nChannels
                    result(end+1:this.nChannels) = {''};
                    result(this.nChannels+1:end) = [];
                end
            end
            function this = set.channelNames(this,value)
                if iscellstr(value)
                    if numel(value) ~= this.nChannels
                        value(end+1:this.nChannels) = {''};
                        value(this.nChannels+1:end) = [];
                    end
                    this.mChannelNames = value(:);
                else
                    error('itaAudio: Wrong data type for channelNames. channelNames has to be cell of strings.')
                end
            end
            
            function result = get.channelUnits(this)
                result = this.mChannelUnits;
                if numel(result) ~= this.nChannels
                    result(end+1:this.nChannels) = {''};
                    result(this.nChannels+1:end) = [];
                end
            end
            function this = set.channelUnits(this,value)
                if iscellstr(value)
                    if numel(value) ~= this.nChannels
                        value(end+1:this.nChannels) = {''};
                        value(this.nChannels+1:end) = [];
                    end
                    this.mChannelUnits = value(:);
                elseif ischar(value) %pdi: all channels with the same unit
                    for idx = 1:this.nChannels
                        this.mChannelUnits{idx} = value;
                    end
                elseif isa(value,'itaValue')
                    this.mChannelUnits{1} = value.unit;
                else
                    error('itaAudio: Wrong data type for channelUnits')
                end
            end
            
            function result = get.channelCoordinates(this)
                result = this.mChannelCoordinates;
                if result.nPoints ~= this.nChannels
                    %if result.nPoints < this.nChannels
                    result = resize(result,this.nChannels);
                end
            end
            function this = set.channelCoordinates(this,value)
                if isa(value,'itaCoordinates')
                    if isa(value,'itaSamplingSPH')
                        value = itaCoordinates(value);
                    end
                    if numel(value) ~= this.nChannels
                        value = resize(value,this.nChannels);
                    end
                    this.mChannelCoordinates = value(:);
                else
                    error('itaAudio: Wrong data type for channelCoordinates')
                end
            end
            
            function result = get.channelOrientation(this)
                result = this.mChannelOrientation;
                if numel(result) ~= this.nChannels
                    %if result.nPoints < this.nChannels
                    result = resize(result,this.nChannels);
                end
            end
            function this = set.channelOrientation(this,value)
                if isa(value,'itaCoordinates')
                    if numel(value) ~= this.nChannels
                        value = resize(value,this.nChannels);
                    end
                    this.mChannelOrientation = value(:);
                else
                    error('itaAudio: Wrong data type for channelOrientation')
                end
            end
            
            function result = get.channelSensors(this)
                result = this.mChannelSensors;
                if numel(result) ~= this.nChannels
                    result(end+1:this.nChannels) = {''};
                    result(this.nChannels+1:end) = [];
                end
            end
            function this = set.channelSensors(this,value)
                if iscellstr(value)
                    if numel(value) ~= this.nChannels
                        value(end+1:this.nChannels) = {''};
                        value(this.nChannels+1:end) = [];
                    end
                    this.mChannelSensors = value(:);
                else
                    error('itaAudio: Wrong data type for channelSensors')
                end
            end
            
            function result = get.channelUserData(this)
                result = this.mChannelUserData;
                if numel(result) ~= this.nChannels
                    result(end+1:this.nChannels) = {[]};
                    result(this.nChannels+1:end) = [];
                end
            end
            function this = set.channelUserData(this,value)
                if iscell(value)
                    if numel(value) ~= this.nChannels
                        value(end+1:this.nChannels) = {[]};
                        value(this.nChannels+1:end) = [];
                    end
                    this.mChannelUserData = value(:);
                else
                    error('itaAudio: Wrong data type for channelUserData')
                end
            end
            
            function result = get.dimensions(this)
                result = this.mDimensions;
            end
            function this = set.dimensions(this,value)
                if isnumeric(value)
                    nChannels = prod(value);
                    if nChannels > prod(this.dimensions)
                        this.channelNames(end+1:nChannels) = {''};
                        this.channelUnits(end+1:nChannels) = {''};
                        this.channelCoordinates = resize(this.channelCoordinates,nChannels);
                        this.channelOrientation = resize(this.channelOrientation,nChannels);
                        this.channelSensors(end+1:nChannels) = {''};
                        this.channelUserData(end+1:nChannels) = {[]};
                    elseif nChannels < prod(this.dimensions)
                        this.channelNames(nChannels+1:end) = [];
                        this.channelUnits(nChannels+1:end) = [];
                        this.channelCoordinates = resize(this.channelCoordinates,nChannels);
                        this.channelOrientation = resize(this.channelOrientation,nChannels);
                        this.channelSensors(nChannels+1:end) = [];
                        this.channelUserData(nChannels+1:end) = [];
                    else
                        % nothing to do
                    end
                    this.mDimensions = value;
                else
                    error('itaAudio: dimensions must be numeric!')
                end
            end
            
            %% Other Stuff
            function result = get.allowDBPlot(this)
                result = this.mAllowDBPlot;
            end
            
            function this = set.allowDBPlot(this,value)
                this.mAllowDBPlot = value;
            end
            
            
            function result = get.objectCoordinates(this)
                result = this.mObjectCoordinates;
            end
            
            function this = set.objectCoordinates(this,value)
                this.mObjectCoordinates = value;
            end
            
            function result = get.objectViewVector(this)
                result = this.mObjectViewVector;
            end
            
            function this = set.objectViewVector(this,value)
                this.mObjectViewVector = value;
            end
            
            function result = get.objectUpVector(this)
                result = this.mObjectUpVector;
            end
            
            function this = set.objectUpVector(this,value)
                this.mObjectUpVector = value;
            end
            
            function write(this,varargin)
                %writes audioObj to disk
                ita_write(this.merge,varargin{:})
            end
            function result = get.dataType(this)
                result = class(this.mData);
            end
            function this = set.dataType(this,value)
                this = cast(this,value);
            end
            
            function result = get.dataTypeOutput(this)
                result = this.mDataTypeOutput;
            end
            function this = set.dataTypeOutput(this,value)
                this.mDataTypeOutput = value;
                if strcmp (this.dataType, value)
                    this.mDataTypeEqual = true;
                else
                    this.mDataTypeEqual = false;
                end
                if strncmp('int', value, 3)
                    ita_verbose_info('Sorry, but ''int'' is really dangerous for dataTypeOutput, please use double or single.',1)
                end
            end
            
            function result = get.dataFactor(this)
                result = this.mDataFactor;
            end
            
            function this = set.dataFactor(this,value)
                this.mDataFactor = value;
                if value ~= 1
                    ita_verbose_info('Please be carefull setting dataFactor!');
                end
            end
            
            function result = get.nBins(this)
                result = get_nBins(this);
            end
            
            function result = get.nSamples(this)
                result = get_nSamples(this);
            end
            
            function this = set.nSamples(this,value)
                this = set_nSamples(this,value);
            end
            
            function result = nChannels(this)
                % get the number of channels
                %dims = size(this.data);
                %result = prod(dims(2:end));
                result = prod(this.dimensions(:));
            end
    
            function res = get_diag(this)
    			% use eye as mask for diagonal
    			res = this(eye(size(this,1)));
            end
    
            function this = diag(this,diagonalshift,blocksize)
                %diagonal of matrix, or build diagonal matrix out of vector
                if nargin == 1 || isempty(diagonalshift)
                    diagonalshift = max(size(this));
                end
                if nargin <= 2
                    blocksize = 1;
                end
                
                if blocksize == 1
                    if size(this,1) > 1 && size(this,2) > 0
                        for idx = 1:blocksize:size(this,1)
                            for jdx = 1:blocksize:size(this,2)
                                if ~(mod(idx,diagonalshift) == mod(jdx,diagonalshift) ) %elements not on the diagonal must be set to zero
                                    this(idx,jdx) = this(idx,jdx)*0;
                                end
                            end
                        end
                    end
                else
                    if size(this,1) > 1 && size(this,2) > 0
                        for idx = 1:blocksize:size(this,1)
                            for jdx = 1:blocksize:size(this,2)
                                
                                %                             this(idx,jdx) = this(idx,jdx)*0;
                                idxx = idx:1:min(idx+diagonalshift/blocksize-1,size(this,1)); %get indeces of submatrix
                                jdxx = jdx:1:min(jdx+diagonalshift/blocksize-1,size(this,2));
                                submatrix = this(idxx , jdxx);
                                
                                if ~(mod(idx,diagonalshift) == mod(jdx,diagonalshift) ) %elements not on the diagonal must be set to zero
                                    submatrix = submatrix * 0;
                                else
                                    %                                 submatrix = diag(submatrix,1);
                                end
                                
                                this (idxx, jdxx) = submatrix;
                                
                            end
                        end
                    end
                end
                
                %             else % diagonal shift
                %                 if size(this,1) > 1 && size(this,2) > 0
                %                     for idx = 1:diagonalshift:size(this,1)
                %                         for jdx = 1:diagonalshift:size(this,2)
                %
                %
                %
                %                         end
                %                     end
                %                 end
                
            end
            
            
            function result = split(this, index)
                %split different channels of the Obj to a new Obj
                if numel(this) > 1 % Multi Instance splitting
                    result = this;
                    for idx = 1:numel(this)
                        result(idx) = this(idx).split(index);
                    end
                    return;
                end
                
                if numel(this.dimensions) == 2
                    newindex = [];
                    for idx = 1:numel(index)
                        newindex = [newindex index(idx):this.mDimensions(1):prod(this.mDimensions)]; %#ok<AGROW>
                    end
                    index = newindex;
                else
                end
                
                %pdi: we have to use a different output variable. otherwise the
                %channel information gets lost! changing 'this' to 'result'
                result = this;
                
                % only use the reduced data
                result.data = this.data(:,index);
                
                % mpo: if we are dealing with a logical index, do a different
                % determination of the dimensions
                if islogical(index)
                    result.dimensions = sum(index);
                else
                    result.dimensions = numel(index);
                end
                
                % and select the appropriate Channel struct(s)
                %% merge channelInfo
                channelFields = properties(this);
                channelFields = channelFields(strcmp('channel',channelFields));
                
                for idchfield = 1:numel(channelFields)
                    thisFieldName = channelFields{idchfield};
                    if any(strcmp('split',methods(this.(thisFieldName)))) % Check if it has a split-function
                        result.(thisFieldName) = split(this.(thisFieldName),index);
                    else % just use cat
                        result.(thisFieldName) = this.(thisFieldName)(index);
                    end
                end
            end
            
            function this = merge(this, varargin)
                % merge several Objs to only one Obj
                
                % Only one
                if nargin == 1 && numel(this) == 1
                    return;
                    
                    % Array
                elseif nargin == 1 && numel(this) > 1
                    if any(isempty(this(:))) % any empty objects
                        ita_verbose_info(sprintf('Merge: Skipping %i empty objects.',sum(isempty(this(:)) )),1)
                        this = this(~isempty(this(:)));
                    end
                    this2 = this(2:end);
                    this = this(1);
                    for idx = 1:numel(this2)
                        this = merge(this,this2(idx));
                    end
                    
                    % Cell
                elseif iscell(this)
                    this = [this{:}];
                    this = merge(this);
                    return;
                    
                    % called merge(a1,a2,a3,a4,...)
                elseif nargin > 2
                    for idx = 1:numel(varargin)
                        this = merge(this,varargin{idx});
                    end
                    
                    % second argument is a cell
                elseif iscell(varargin{1})
                    tmp = varargin{1};
                    this = [tmp{:}];
                    clear tmp;
                    this = merge(this);
                    
                    % Two itaAudios
                elseif isa(varargin{1},'itaSuper')
                    if isempty(this)
                        this = varargin{1};
                    else
                        this2 = varargin{1};
                        [this, this2] = prepare4merge(this,this2);
                        
                        %% merge data
                        thischannels = this.nChannels;
                        this.data = [this.data  this2.data];
                        
                        %% merge channelInfo
                        channelFields = properties(this);
                        channelFields = channelFields(strcmp('channel',channelFields));
                        
                        for idchfield = 1:numel(channelFields)
                            thisFieldName = channelFields{idchfield};
                            if any(strcmp('merge',methods(this.(thisFieldName)))) % Check if it has a merge-function
                                this.(thisFieldName) = merge(split(this.(thisFieldName),(1:thischannels)),  this2.(thisFieldName));
                            else % just use cat
                                this.(thisFieldName) = [this.(thisFieldName)(1:thischannels);  this2.(thisFieldName)(:)];
                            end
                        end
                        
                        %% Merge history
                        this = ita_metainfo_add_historyline(this,'merge',this2,'withSubs');
                    end
                else
                    ita_verbose_info('merge@itaSuper: I dont know what to do with this argument, ignoring it',0);
                end
                
            end
            
            function [this1, this2] = prepare4merge(this1, this2)
                % Prepare two object for merge, check if compatible and try to fix problems
                
                %% Check
                
                if ~strcmpi(this1.domain,this2.domain)
                    error('Merge: These objects won''t work together: ill-suited domain')
                end
                if this1.nSamples ~= this2.nSamples 
                    error('Merge: These objects won''t work together: ill-suited number of samples');
                end
                if ~strcmp(class(this1),class(this2)) 
                    error('Merge: These objects won''t work together: ill-suited class');
                end
                if  numel(this1.dimensions) ~= numel(this2.dimensions)
                    error('Merge: These objects won''t work together: ill-suited dimensions');
                end
    
                
            end
            
            function result = ch(this, channels)
                %split single channels from multichannel Obj
                result = split(this,channels); %pdi
                %             if nargin > 1
                %                 result.data = this.data(:,channels);
                %             end
            end
            
            
            %% new plot naming
            function plot_cmplx(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_cmplx(this,varargin{:})
            end
            function plot_freq(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_freq(this,varargin{:})
            end
            function plot_phase(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_phase(this,varargin{:})
            end
            function plot_freq_phase(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_freq_phase(this,varargin{:})
            end
            function plot_freq_groupdelay(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_freq_groupdelay(this,varargin{:})
            end
            function plot_time(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_time(this,varargin{:})
            end
            function plot_time_dB(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_time_dB(this,varargin{:})
            end
            function plot_spectrogram(this,varargin)
                %plot spectrogram (itaAudio)
                ita_plot_spectrogram(this,varargin{:})
            end
            function plot_all(this,varargin)
                %plot everything in one plot (if freq and time data available)
                ita_plot_all(this,varargin{:})
            end
            
            
            %% get DATA in dB
            function result = freqData_dB(this,varargin)
                %Returns frequency data in dB
                [sArgs] = ita_parse_arguments(struct('log_prefix',[]),varargin);
                
                %get logarithmic frequency data 20*log10(abs(Obj.freq)/referenceValue)
                [~,  refValues, log_prefix] = itaValue.log_reference(this.channelUnits);
                if sArgs.log_prefix
                    log_prefix = sArgs.log_prefix;
                end
                % changed from log10(x) to log(x)/log(10) because it is faster
                result = bsxfun(@times, log_prefix(:).'./log(10), log(abs(this.freqData + realmin))); %plus eps to avoid -Inf
                result = bsxfun(@plus,result, log_prefix(:).'./log(10).*log(1./refValues(:).'));
            end
            
            function result = timeData_dB(this,varargin)
                %Returns frequency data in dB
                [sArgs] = ita_parse_arguments(struct('log_prefix',[]),varargin);
                
                %get logarithmic frequency data 20*log10(abs(Obj.freq)/referenceValue)
                [~,  refValues, log_prefix] = itaValue.log_reference(this.channelUnits);
                if sArgs.log_prefix
                    log_prefix = sArgs.log_prefix;
                end
                % changed from log10(x) to log(x)/log(10) because it is faster
                result = bsxfun(@times, log_prefix(:).'./log(10), log(abs(this.timeData + realmin))); %plus eps to avoid -Inf
                result = bsxfun(@plus,result, log_prefix(:).'./log(10).*log(1./refValues(:).'));
            end
            
            %% Overloaded functions
            
            function scatter(this,freq,varargin)
                %plot data by using coordinates
                % scatter(Obj, freq(double), ['axishandle',handle, 'size', double, 'title', titleStr])
                sArgs = struct('axishandle',[],'size',10,'title',this.comment,'noabs',false,'filled','square');
                sArgs = ita_parse_arguments(sArgs,varargin);
                if isempty(sArgs.axishandle)
                    figure;
                else
                    axes(sArgs.axishandle);
                end
                if sArgs.noabs
                    scatter(this.channelCoordinates.x,this.channelCoordinates.y, ...
                        this.freq2value(freq)*0+sArgs.size,(this.freq2value(freq)),'filled',sArgs.filled);
                else
                    scatter(this.channelCoordinates.x,this.channelCoordinates.y, ...
                        this.freq2value(freq)*0+sArgs.size,abs(this.freq2value(freq)),'filled',sArgs.filled);
                end
                axis image; colorbar
                title([sArgs.title ' (' this.channelUnits{1} ') - ' num2str(freq) ' Hz ' ]);
                xlabel('x');
                ylabel('y');
            end
            
            
            %         function pcolor(this,freq,varargin)
            %             %plot data by using coordinates
            %             % pcolor(Obj, freq(double), ['axishandle',handle, 'size', double, 'title', titleStr])
            % pdi: does not work in this way !!!
            %             sArgs = struct('axishandle',[],'size',10,'title',this.comment,'noabs',false);
            %             sArgs = ita_parse_arguments(sArgs,varargin);
            %             if isempty(sArgs.axishandle)
            %                 figure;
            %             else
            %                 axes(sArgs.axishandle);
            %             end
            %             if sArgs.noabs
            %                 pcolor(this.channelCoordinates.x,this.channelCoordinates.y, ...
            %                 this.freq2value(freq));
            %             else
            %                 pcolor(this.channelCoordinates.x,this.channelCoordinates.y, ...
            %                     this.freq2value(freq)*0+sArgs.size,abs(this.freq2value(freq)),'filled','square');
            %             end
            %             axis image; colorbar
            %             title([sArgs.title ' (' this.channelUnits{1} ') - ' num2str(freq) ' Hz ' ]);
            %             xlabel('x');
            %             ylabel('y');
            %         end
            
        end
        
        methods(Hidden = true)
            % shortcuts for plots!
            function pt(this,varargin)
                ita_plot_time(this,varargin{:})
            end
            function ptd(this,varargin)
                ita_plot_time_dB(this,varargin{:})
            end
            function pf(this,varargin)
                ita_plot_freq(this,varargin{:})
            end
            function pfp(this,varargin)
                ita_plot_freq_phase(this,varargin{:})
            end
            function pfg(this,varargin)
                ita_plot_freq_groupdelay(this,varargin{:})
            end
        end
        
        %% ******** Hidden Methods *******************************************
        methods(Hidden = true)
            function res = legend(this,varargin)
                % build a cell of strings for the plot legend
                if nargin == 1
                    mode = 'log';
                else
                    mode = varargin{1};
                end
                tmp_channelNames = this.channelNames;
                tmp_channelUnits = this.channelUnits;
                tmp_channelUnits(strcmpi(tmp_channelUnits,'')) = {'1'};
    			res = cell(1,this.nChannels);
                for idx = 1:this.nChannels
                    if strcmpi(mode,'nodb')
                        res{idx} = [tmp_channelNames{idx} ' [' tmp_channelUnits{idx} ']' ];
                    elseif strcmpi(mode,'nothing')
                        res{idx} = [tmp_channelNames{idx}];
                    else
                        res{idx} = [tmp_channelNames{idx} ' [dB re ' itaValue.log_reference( tmp_channelUnits{idx}) ']' ];
                    end
                end
            end
            
    		% TODO What is this supposed to do?
            % function res = log_reference(this)
            %     
            % end
            
            function result = get_data(this)
                if ~this.mDataTypeEqual || any(this.mDataFactor ~= 1)
                    if strncmp('int', this.dataTypeOutput, 3)
                        result = cast(this.mData,this.dataTypeOutput);
                    else
                        result = cast(this.mData,this.dataTypeOutput)  .* this.mDataFactor;
                    end
                else
                    result = this.mData;
                end
            end
            function this = set_data(this,value)
                % this functions is needed for class itaAudioDevNull
                % and for the check of even number of samples
                if ~isa(value, this.dataType)
                    if any(strncmp('int', this.dataType, 3)) && ~any(strcmp('int', this.dataTypeOutput, 3))
                        this.dataFactor = double(max(max(abs(value)))) ./ (double(intmax(this.dataType))-1);
                        value = value ./ this.mDataFactor;
                    end
                    wstate = [warning('off','MATLAB:intConvertNonIntVal') warning('off','MATLAB:intConvertNaN')];
                    this.mData = cast(value,this.dataType);
                    warning(wstate);
                    ita_verbose_info('Changing data-type. Some information may be lost',2)
                else
                    this.mData = value;
                end
            end
            function result = get_nBins(this)
                if this.isFreq
                    result = size(this.data,1);
                else
                    result = this.nSamples2nBins;
                end
            end
            
            function result = get_nSamples(this)
                if this.isTime
                    result = size(this.data,1);
                else
                    result = this.nBins2nSamples;
                end
            end
            
            %% is* Stuff
            function result = isTime(this)
                result = zeros(size(this));
                for ind = 1:numel(result)
                    result(ind) = strcmp(this(ind).domain,'time');
                end
            end
            function result = isFreq(this)
                result = zeros(size(this));
                for ind = 1:numel(result)
                    result(ind) = strcmp(this(ind).domain,'freq');
                end
            end
            
            function result = isempty(this)
                result = false(size(this));
                for idx = 1:numel(this)
                    result(idx) = isempty(this(idx).data);
                end
            end
            function nBins = nSamples2nBins(this)       %#ok<MANU>
                nBins = NaN;
            end
            
            function nSamples = nBins2nSamples(this) %#ok<MANU>
                nSamples = NaN;
            end
            
            function sObj = saveobj(this)
                
                % Called whenever an object is saved
                sObj = saveobj@itaMeta(this);
                
                this.dataTypeOutput = this.dataType; % Save the extact data we really have
                
                % Copy all properties that were defined to be saved
                propertylist = itaSuper.propertiesSaved;
                for idx = 1:numel(propertylist)
                    sObj.(propertylist{idx}) = this.(propertylist{idx});
                end
            end
            
            function displayLineStart(this)
                %internal stuff
                classnameString = ['|' class(this) '|'];
                result = this.LINE_START;
                result(3:(2+length(classnameString))) = classnameString;
                disp(result);
            end
            function displayChannelString(this,fHandle)
                prefName = 'dispVerboseChannels'; dispName = 'channels';
                global lastDiplayedVariableName
                nChannels = this.nChannels;
                if nChannels == 1; dispName = dispName(1:end-1); end %get rid off plural 's'
                dispName = [num2str(nChannels) ' ' dispName ' (' this.dimString ') ' ];
                if ita_preferences('dispVerboseChannels')
                    middleLine = this.LINE_MIDDLE;
                    middleLine(3:(2+length(dispName))) = dispName;
                    fprintf(['<a href = "matlab: ita_preferences(''' prefName ''',0); display(' lastDiplayedVariableName ')">-</a> ' middleLine(3:end) '\n']);
                    fHandle(this);
                else
                    fprintf(['<a href = "matlab: ita_preferences(''' prefName ''',1); display(' lastDiplayedVariableName ');">+</a> ' dispName '\n']);
                end
            end
            
            function displayOptions(this, prefName, fHandle)
                global lastDiplayedVariableName
                dispName = lower(prefName(12:end));
                if strcmp(dispName,'channels')
                    nChannels = this.nChannels;
                    if nChannels == 1; dispName = dispName(1:end-1); end %get rid off plural 's'
                    dispName = [num2str(nChannels) ' ' dispName ' (' this.dimString ') ' ];
                end
                dispName = [dispName ' '];
                if ~strcmpi(prefName, 'dispVerboseErrors') || any(numel(this.errorLog)) % get rid off error display if no errors
                    if ita_preferences(prefName)
                        middleLine = this.LINE_MIDDLE;
                        middleLine(3:(2+length(dispName))) = dispName;
                        fprintf(['<a href = "matlab: ita_preferences(''' prefName ''',0); display(' lastDiplayedVariableName ')">-</a> ' middleLine(3:end) '\n']);
                        fHandle(this);
                    else
                        fprintf(['<a href = "matlab: ita_preferences(''' prefName ''',1); display(' lastDiplayedVariableName ');">+</a> ' dispName '\n']);
                    end
                end
            end
            function displayLineEnd(this)
                disp(this.LINE_END);
            end
            function displayEndOfClass(this, classname)
                classnameString = ['(' classname ')'];
                result = repmat(' ', 1, length(this.LINE_START) - length(classnameString));
                disp([result classnameString]);
            end
            
            function result = unit(this,value)
                % get or set itaValues where the units are the same as in the itaSuper
                if nargin == 1 % only get
                    for idx = 1:size(this,1)
                        for jdx = 1:size(this,2)
                            for ndx = 1:this(idx,jdx).nChannels
                                result(idx,jdx,ndx) = itaValue(1,this(idx,jdx).channelUnits{ndx});
                            end
                        end
                    end
                else % set values
                    for idx = 1:size(this,1)
                        for jdx = 1:size(this,2)
                            for ndx = 1:this(idx,jdx).nChannels
                                this(idx,jdx,ndx).channelUnits{ndx} = value(idx,jdx);
                            end
                        end
                    end
                    result = this;
                end
            end
            
            function plot_multiple(this,plotStr,varargin)
                % plot multi instance in subplots
                %
                % syntax e.g. ARRAY.plot_multiple('plot_freq',xlim,[100 5000])
                h = ita_plottools_figure;
                
                for idx = 1:numel(this)
                    axh(idx) = subplot(numel(this), 1, idx);
                    this(idx).(plotStr)('axes_handle',axh(idx), 'figure_handle',h,varargin{:});
                end
                linkaxes(axh);
                
            end
            
        end
        
        methods(Hidden = true)
            function showHistory(this)
                display(this)
                disp('  History Log ')
                ita_metainfo_show_history(this);
            end
            
            function dimString = dimString(this)
                % get a nice dimension string
                dimString = [];
                tmp_dimensions = this.dimensions;
                for ind = 1:numel(tmp_dimensions)
                    dimString = [dimString num2str(tmp_dimensions(ind))]; %#ok<AGROW>
                    if ind < numel(tmp_dimensions)
                        dimString = [dimString ' x ']; %#ok<AGROW>
                    end
                end
            end
            
            %% some plot routine routes
            function plot_TPA(this,varargin)
                ita_plot_TPA(this,varargin{:})
            end
            
            function plot_spkphase(this,varargin)
                %plot spectrum and phase (if freq data available)
                ita_plot_freq_phase(this,varargin{:})
            end
            function plot_spkgdelay(this,varargin)
                %plot spectrum and group delay (if freq data available)
                ita_plot_freq_groupdelay(this,varargin{:})
            end
            function plot_spk(this,varargin)
                %plot spectrum (if freq data available)
                ita_plot_freq(this,varargin{:})
            end
            function plot_dat(this,varargin)
                %plot time history (if time data available)
                ita_plot_time(this,varargin{:})
            end
            function plot_dat_dB(this,varargin)
                %plot time energy history  (if freq data available)
                ita_plot_time_dB(this,varargin{:})
            end
            
        end
        
        
        
        %% Static Methods
        methods(Static, Hidden = true)
            function this = loadobj(sObj)
                % Called when an object is loaded
                sObj = rmfield(sObj,{'classrevision', 'classname'}); % Remove these fields cause no more needed, but we could use them for special case handling (e.g. old versions)
                sObj.dataType = class(sObj.data); % Set dataType equal to class(data)
                this = itaSuper(sObj); % Just call constructor, he will take care
                switch this.dataType(1:3)
                    case {'int'}
                        this.dataTypeOutput = 'single'; %Save solution
                    otherwise
                        this.dataTypeOutput = this.dataType;
                end
            end
            function result = metaDataFields
                % meta data fields for copying
                result = {'channelNames','channelUnits','channelCoordinates','channelOrientation','channelSensors','channelUserData',...
                    'comment' 'history','objectCoordinates','objectViewVector','objectUpVector'};
            end
            function result = propertiesSaved
                % important: first domain, then data
                result = {'domain','data','dimensions',...
                    'channelNames','channelUnits','channelCoordinates',...
                    'channelOrientation','channelSensors','channelUserData',...
                    'dataType','dataTypeOutput','dataFactor','allowDBPlot','objectCoordinates','objectViewVector','objectUpVector'};
            end
            function res = LINE_MIDDLE()
                res = repmat('-',1,itaSuper.LINE_LENGTH);
            end
            function res = LINE_END()
                res = repmat('-',1,itaSuper.LINE_LENGTH);
            end
            function res = LINE_START()
                res = repmat('=',1,itaSuper.LINE_LENGTH);
            end
            
        end
    end