Mercurial > hg > camir-aes2014
diff toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirflux.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/toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirflux.m Tue Feb 10 15:05:51 2015 +0000 @@ -0,0 +1,254 @@ +function varargout = mirflux(orig,varargin) +% f = mirflux(x) measures distance between successive frames. +% First argument: +% If x is a spectrum, this corresponds to spectral flux. +% But the flux of any other data can be computed as well. +% If x is an audio file or audio signal, the spectral flux is +% computed by default. +% Optional arguments: +% f = mirflux(x,'Frame',...) specifies the frame parameters, if x is +% not already decomposed into frames. Default values are frame +% length of .2 seconds and hop factor of 1.3. +% f = mirflux(x,'Dist',d) specifies the distance between +% successive frames: (IF 'COMPLEX': DISTANCE = 'CITY' ALWAYS) +% d = 'Euclidian': Euclidian distance (Default) +% d = 'City': City-block distance +% d = 'Cosine': Cosine distance (or normalized correlation) +% f = mirflux(...,'Inc'): Only positive difference between frames are +% summed, in order to focus on increase of energy solely. +% f = mirflux(...,'Complex'), for spectral flux, combines use of +% energy and phase information (Bello et al, 2004). +% f = mirflux(...,'Halfwave'): performs a half-wave rectification on +% the result. +% f = mirflux(...,'Median',l,C): removes small spurious peaks by +% subtracting to the result its median filtering. The median +% filter computes the point-wise median inside a window of length +% l (in seconds), that includes a same number of previous and +% next samples. C is a scaling factor whose purpose is to +% artificially rise the curve slightly above the steady state of +% the signal. If no parameters are given, the default values are: +% l = 0.2 s. and C = 1.3 +% f = mirflux(...,'Median',l,C,'Halfwave'): The scaled median +% filtering is designed to be succeeded by the half-wave +% rectification process in order to select peaks above the +% dynamic threshold calculated with the help of the median +% filter. The resulting signal is called "detection function" +% (Alonso, David, Richard, 2004). To ensure accurate detection, +% the length l of the median filter must be longer than the +% average width of the peaks of the detection function. +% +% (Bello et al, 2004) Juan P. Bello, Chris Duxbury, Mike Davies, and Mark +% Sandler, On the Use of Phase and Energy for Musical Onset Detection in +% the Complex Domain, IEEE SIGNAL PROCESSING LETTERS, VOL. 11, NO. 6, +% JUNE 2004 + + dist.key = 'Dist'; + dist.type = 'String'; + dist.choice = {'Euclidian','City','Cosine'}; %PDIST???? (euclidean) + dist.default = 'Euclidian'; + option.dist = dist; + + inc.key = 'Inc'; + inc.type = 'Boolean'; + inc.default = 0; + option.inc = inc; + + complex.key = 'Complex'; + complex.type = 'Boolean'; + complex.default = 0; + option.complex = complex; + + h.key = 'Halfwave'; + h.type = 'Boolean'; + h.default = 0; + h.when = 'After'; + option.h = h; + + median.key = 'Median'; + median.type = 'Integer'; + median.number = 2; + median.default = [0 0]; + median.keydefault = [.2 1.3]; + median.when = 'After'; + option.median = median; + + frame.key = 'Frame'; + frame.type = 'Integer'; + frame.number = 2; + frame.default = [.05 .5]; + option.frame = frame; + +specif.option = option; + +varargout = mirfunction(@mirflux,orig,varargin,nargout,specif,@init,@main); + + +function [x type] = init(x,option) +if isamir(x,'miraudio') + if isframed(x) + x = mirspectrum(x); + else + x = mirspectrum(x,'Frame',option.frame.length.val,option.frame.length.unit,... + option.frame.hop.val,option.frame.hop.unit); + end +end +if isa(x,'mirdesign') + x = set(x,'Overlap',1); +end +type = 'mirscalar'; + + +function f = main(s,option,postoption) +if iscell(s) + s = s{1}; +end +t = get(s,'Title'); +if isa(s,'mirscalar') && ... + (strcmp(t,'Harmonic Change Detection Function') || ... + (length(t)>4 && strcmp(t(end-3:end),'flux')) || ... + (length(t)>5 && strcmp(t(end-4:end-1),'flux'))) + if not(isempty(postoption)) + f = modif(s,postoption); + end +else + if isa(s,'mirspectrum') + t = 'Spectral'; + end + m = get(s,'Data'); + if option.complex + if not(isa(s,'mirspectrum')) + error('ERROR IN MIRFLUX: ''Complex'' option only defined for spectral flux.'); + end + ph = get(s,'Phase'); + end + param.complex = option.complex; + param.inc = option.inc; + fp = get(s,'FramePos'); + if strcmp(t,'Tonal centroid') + t = 'Harmonic Change Detection Function'; + else + t = [t,' flux']; + end + disp(['Computing ' t '...']) + ff = cell(1,length(m)); + newsr = cell(1,length(m)); + dist = str2func(option.dist); + %[tmp s] = gettmp(s); %get(s,'Tmp'); + for h = 1:length(m) + ff{h} = cell(1,length(m{h})); + if not(iscell(m{h})) + m{h} = {m{h}}; + end + for i = 1:length(m{h}) + mi = m{h}{i}; + if size(mi,3) > 1 && size(mi,1) == 1 + mi = reshape(mi,size(mi,2),size(mi,3))'; + end + if option.complex + phi = ph{h}{i}; + end + fpi = fp{h}{i}; + %if 0 %not(isempty(tmp)) && isstruct(tmp) && isfield(tmp,'mi') + % mi = [tmp.mi mi]; + % fpi = [tmp.fpi fpi]; + %end + nc = size(mi,2); + np = size(mi,3); + if nc == 1 + warning('WARNING IN MIRFLUX: Flux can only be computed on signal decomposed into frames.'); + ff{h}{i} = NaN(1,1,np); + else + if option.complex + fl = zeros(1,nc-2,np); + for k = 1:np + d = diff(phi(:,:,k),2,2); + d = d/(2*pi) - round(d/(2*pi)); + g = sqrt(mi(:,3:end,k).^2 + mi(:,2:(end-1),k).^2 ... + - 2.*mi(:,3:end,k)... + .*mi(:,2:(end-1),k)... + .*cos(d)); + fl(1,:,k) = sum(g); + end + fp{h}{i} = fpi(:,3:end); + else + fl = zeros(1,nc-1,np); + for k = 1:np + for j = 1:nc-1 + fl(1,j,k) = dist(mi(:,j,k),mi(:,j+1,k),option.inc); + end + end + fp{h}{i} = fpi(:,2:end); + end + ff{h}{i} = fl; + %tmp.mi = mi(:,end,:); + %tmp.fpi = fpi(:,end,:); + end + end + %tmp = []; + if size(fpi,2)<2 + newsr{h} = 0; + else + newsr{h} = 1/(fpi(1,2)-fpi(1,1)); + end + end + f = mirscalar(s,'Data',ff,'FramePos',fp,'Sampling',newsr,... + 'Title',t,'Parameter',param); %,'Tmp',tmp); + %f = settmp(f,tmp); + if not(isempty(postoption)) + f = modif(f,postoption); + end +end + + +function f = modif(f,option) +fl = get(f,'Data'); +r = get(f,'Sampling'); +for h = 1:length(fl) + for i = 1:length(fl{h}) + fli = fl{h}{i}; + nc = size(fli,2); + np = size(fli,3); + if option.median(1) + ffi = zeros(1,nc,np); + lr = round(option.median(1)*r{i}); + for k = 1:np + for j = 1:nc + ffi(:,j,k) = fli(:,j,k) - ... + option.median(2) * median(fli(:,max(1,j-lr):min(nc-1,j+lr),k)); + end + end + fli = ffi; + end + if option.h + fli = hwr(fli); + end + fl{h}{i} = fli; + end +end +f = set(f,'Data',fl); + + +function y = Euclidian(mi,mj,inc) +if inc + y = sqrt(sum(max(0,(mj-mi)).^2)); +else + y = sqrt(sum((mj-mi).^2)); +end + + +function y = City(mi,mj,inc) +if inc + y = sum(max(0,(mj-mi))); +else + y = sum(abs(mj-mi)); +end + + +function d = Cosine(r,s,inc) +nr = sqrt(r'*r); +ns = sqrt(s'*s); +if or(nr == 0, ns == 0); + d = 1; +else + d = 1 - r'*s/nr/ns; +end \ No newline at end of file