wolffd@0: function varargout = mirinharmonicity(orig,varargin) wolffd@0: % ih = mirinharmonicity(x) estimates the inharmonicity of x, i.e., the wolffd@0: % amount of partials that are not multiples of the fundamental wolffd@0: % frequency. wolffd@0: % x can be either an audio file, a miraudio or a mirspectrum object. wolffd@0: % WARNING: This function presupposes that there is only one fundamental wolffd@0: % frequency. wolffd@0: % Optional argument: wolffd@0: % mirinharmonicity(...,'f0',f) bases the computation of the wolffd@0: % inharmonicity on the fundamental frequency indicated by f. wolffd@0: % Default value: f = mirpitch(...,'Mono') wolffd@0: % [ih,s] = mirinharmonicity(x) also displays the spectrum used for the wolffd@0: % computation of the inharmonicity. wolffd@0: % [ih,s,p] = mirinharmonicity(x) also displays the result of the wolffd@0: % estimation of the fundamental frequency. wolffd@0: wolffd@0: f0.key = 'f0'; wolffd@0: f0.default = []; wolffd@0: option.f0 = f0; wolffd@0: wolffd@0: frame.key = 'Frame'; wolffd@0: frame.type = 'Integer'; wolffd@0: frame.number = 2; wolffd@0: frame.default = [0 0]; wolffd@0: frame.keydefault = [.1 .125]; wolffd@0: option.frame = frame; wolffd@0: wolffd@0: specif.option = option; wolffd@0: wolffd@0: varargout = mirfunction(@mirinharmonicity,orig,varargin,nargout,specif,@init,@main); wolffd@0: wolffd@0: wolffd@0: function [i type] = init(x,option) wolffd@0: if isamir(x,'miraudio') wolffd@0: if option.frame.length.val wolffd@0: s = mirspectrum(x,'Frame',option.frame.length.val,... wolffd@0: option.frame.length.unit,... wolffd@0: option.frame.hop.val,... wolffd@0: option.frame.hop.unit); wolffd@0: else wolffd@0: s = mirspectrum(x); wolffd@0: end wolffd@0: else wolffd@0: s = x; wolffd@0: end wolffd@0: if isempty(option.f0) wolffd@0: if option.frame.length.val wolffd@0: p = mirpitch(x,'Mono','Frame',option.frame.length.val,... wolffd@0: option.frame.length.unit,... wolffd@0: option.frame.hop.val,... wolffd@0: option.frame.hop.unit); wolffd@0: else wolffd@0: p = mirpitch(x,'Mono'); wolffd@0: end wolffd@0: else wolffd@0: p = option.f0; wolffd@0: end wolffd@0: i = {s,p}; wolffd@0: type = {'mirscalar','mirspectrum','mirscalar'}; wolffd@0: wolffd@0: wolffd@0: function ih = main(x,option,postoption) wolffd@0: if isa(x{2},'mirdesign') wolffd@0: x = x{1}; wolffd@0: end wolffd@0: s = x{1}; wolffd@0: p = x{2}; wolffd@0: if iscell(p) wolffd@0: p = p{1}; wolffd@0: end wolffd@0: m = get(s,'Magnitude'); wolffd@0: f = get(s,'Frequency'); wolffd@0: fp1 = get(s,'FramePos'); wolffd@0: if isnumeric(p) wolffd@0: pf = {{{p}}}; wolffd@0: else wolffd@0: pf = get(p,'Data'); wolffd@0: fp2 = get(p,'FramePos'); wolffd@0: end wolffd@0: v = cell(1,length(m)); wolffd@0: for h = 1:length(m) wolffd@0: v{h} = cell(1,length(m{h})); wolffd@0: for i = 1:length(m{h}) wolffd@0: mi = m{h}{i}; wolffd@0: fi = f{h}{i}; wolffd@0: pfi = pf{h}{i}; wolffd@0: v{h}{i} = zeros(1,size(mi,2),size(mi,3)); wolffd@0: if not(size(mi,2) == size(pfi,2)) wolffd@0: beg = find(fp2{h}{i}(1,:) == fp1{h}{i}(1,1)); wolffd@0: if isempty(beg) || (beg + size(mi,2)-1 > size(pfi,2)) wolffd@0: error('ERROR IN MIRINHARMONICITY: The ''f0'' argument should have the same frame decomposition than the main input.'); wolffd@0: end wolffd@0: pfi = pfi(:,beg:beg+size(mi,2)-1); wolffd@0: end wolffd@0: for j = 1:size(mi,3) wolffd@0: for k = 1:size(mi,2) wolffd@0: mk = mi(:,k,j); wolffd@0: fk = fi(:,k,j); wolffd@0: pfk = pfi(:,k); wolffd@0: if isempty(pfk{1}) wolffd@0: v{h}{i}(1,k,j) = NaN; wolffd@0: else wolffd@0: r = fk/pfk{1}(1); wolffd@0: rr = 2*abs(r-round(r)); wolffd@0: if isempty(rr) wolffd@0: v{h}{i}(1,k,j) = NaN; wolffd@0: else wolffd@0: v{h}{i}(1,k,j) = sum(rr.*mk) / sum(mk); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: ih = mirscalar(s,'Data',v,'Title','Inharmonicity'); wolffd@0: if isa(p,'mirdata') wolffd@0: ih = {ih s p}; wolffd@0: else wolffd@0: ih = {ih s}; wolffd@0: end