diff toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirtempo.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/mirtempo.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,405 @@
+function varargout = mirtempo(x,varargin)
+%   t = mirtempo(x) evaluates the tempo in beats per minute (BPM).
+%   Optional arguments:
+%       mirtempo(...,'Total',m) selects not only the best tempo, but the m
+%           best tempos.
+%       mirtempo(...,'Frame',l,h) orders a frame decomposition of window
+%           length l (in seconds) and hop factor h, expressed relatively to
+%           the window length. For instance h = 1 indicates no overlap.
+%           Default values: l = 3 seconds and h = .1
+%       mirtempo(...,'Min',mi) indicates the lowest tempo taken into
+%           consideration, expressed in bpm.
+%           Default value: 40 bpm.
+%       mirtempo(...,'Max',ma) indicates the highest tempo taken into
+%           consideration, expressed in bpm.
+%           Default value: 200 bpm.
+%       mirtempo(...,s) selects the tempo estimation strategy:
+%           s = 'Autocor': Approach based on the computation of the
+%               autocorrelation. (Default strategy)
+%               Option associated to the mirautocor function can be
+%               passed here as well (see help mirautocor):
+%                   'Enhanced' (toggled on by default here)
+%           s = 'Spectrum': Approach based on the computation of the
+%               spectrum .
+%               Option associated to the mirspectrum function can be
+%               passed here as well (see help mirspectrum):
+%                   'ZeroPad' (set by default to 10000 samples)
+%                   'Prod' (toggled off by default)
+%           These two strategies can be combined: the autocorrelation
+%               function is translated into the frequency domain in order
+%               to be compared to the spectrum curve.
+%               tempo(...,'Autocor','Spectrum') multiplies the two curves.
+%           Alternatively, an autocorrelation function ac or a spectrum sp
+%               can be directly passed to the function tempo:
+%                   mirtempo(ac) or mirtempo(sp)
+%       The options related to the onset detection phase can be specified 
+%               here as well (see help mironsets):
+%               onset detection strategies: 'Envelope', 'DiffEnvelope'
+%               (corresponding to 'Envelope', 'Diff'), 'SpectralFlux,
+%               'Pitch', 'Log', 'Mu', 'Filterbank'
+%               mironsets(...,'Sum',w) specifies when to sum the channels.
+%                   Possible values:
+%                       w = 'Before': sum before the autocorrelation or
+%                           spectrum computation.
+%                       w = 'After': autocorrelation or spectrum computed
+%                           for each band, and summed into a "summary".
+%               mirenvelope options: 'HalfwaveCenter','Diff' (toggled on by
+%                   default here),'HalfwaveDiff','Center','Smooth',
+%                   'Sampling'
+%               mirflux options: 'Inc','Halfwave','Complex','Median'
+%       mirtempo(...,'Resonance',r) specifies the resonance curve, which
+%           emphasizes the periods that are more easily perceived.
+%           Possible values: 'ToiviainenSnyder' (default), 0 (toggled off)
+%   Optional arguments used for the peak picking (cf. help mirpeaks)
+%       mirtempo(...,'Contrast',thr): a threshold value. A given local
+%           maximum will be considered as a peak if its distance with the
+%           previous and successive local minima (if any) is higher than 
+%           this threshold. This distance is expressed with respect to the
+%           total amplitude of the autocorrelation function.
+%               if no value for thr is given, the value thr=0.1 is chosen
+%                   by default.
+%
+%   [t,p] = mirtempo(...) also displays the result of the signal analysis
+%       leading to the tempo estimation, and shows in particular the
+%       peaks corresponding to the tempo values.
+            
+    
+        sum.key = 'Sum';
+        sum.type = 'String';
+        sum.choice = {'Before','After','Adjacent',0};
+        sum.default = 'Before';
+    option.sum = sum;
+        
+%% options related to mironsets:    
+
+        frame.key = 'Frame';
+        frame.type = 'Integer';
+        frame.number = 2;
+        frame.default = [0 0];
+        frame.keydefault = [3 .1];
+    option.frame = frame;
+    
+        fea.type = 'String';
+        fea.choice = {'Envelope','DiffEnvelope','SpectralFlux','Pitch'};
+        fea.default = 'Envelope';
+    option.fea = fea;
+    
+    %% options related to 'Envelope':
+    
+            envmeth.key = 'Method';
+            envmeth.type = 'String';
+            envmeth.choice = {'Filter','Spectro'};
+            envmeth.default = 'Filter';
+        option.envmeth = envmeth;
+    
+        %% options related to 'Filter':
+
+                fb.key = 'Filterbank';
+                fb.type = 'Integer';
+                fb.default = 10;
+            option.fb = fb;
+
+                fbtype.key = 'FilterbankType';
+                fbtype.type = 'String';
+                fbtype.choice = {'Gammatone','Scheirer','Klapuri'};
+                fbtype.default = 'Gammatone';
+            option.fbtype = fbtype;
+
+                ftype.key = 'FilterType';
+                ftype.type = 'String';
+                ftype.choice = {'IIR','HalfHann'};
+                ftype.default = 'IIR';
+            option.ftype = ftype;
+
+        %% options related to 'Spectro':
+        
+                band.type = 'String';
+                band.choice = {'Freq','Mel','Bark','Cents'};
+                band.default = 'Freq';
+            option.band = band;
+
+        
+            chwr.key = 'HalfwaveCenter';
+            chwr.type = 'Boolean';
+            chwr.default = 0;
+        option.chwr = chwr;
+
+            diff.key = 'Diff';
+            diff.type = 'Boolean';
+            diff.default = 1; % Different default for mirtempo
+        option.diff = diff;
+
+            diffhwr.key = 'HalfwaveDiff';
+            diffhwr.type = 'Integer';
+            diffhwr.default = 0;
+            diffhwr.keydefault = 1;
+        option.diffhwr = diffhwr;
+        
+            lambda.key = 'Lambda';
+            lambda.type = 'Integer';
+            lambda.default = 1;
+        option.lambda = lambda;
+
+            mu.key = 'Mu'; 
+            mu.type = 'Boolean'; 
+            mu.default = 0; 
+	        option.mu = mu; 
+        
+            log.key = 'Log';
+            log.type = 'Boolean';
+            log.default = 0;
+        option.log = log;
+
+            c.key = 'Center';
+            c.type = 'Boolean';
+            c.default = 0;
+        option.c = c;
+
+            aver.key = 'Smooth';
+            aver.type = 'Integer';
+            aver.default = 0;
+            aver.keydefault = 30;
+        option.aver = aver;
+
+            sampling.key = 'Sampling';
+            sampling.type = 'Integer';
+            sampling.default = 0;
+        option.sampling = sampling;
+
+    %% options related to 'SpectralFlux'
+    
+            complex.key = 'Complex';
+            complex.type = 'Boolean';
+            complex.default = 0;
+        option.complex = complex;
+
+            inc.key = 'Inc';
+            inc.type = 'Boolean';
+            inc.default = 1;
+        option.inc = inc;
+
+            median.key = 'Median';
+            median.type = 'Integer';
+            median.number = 2;
+            median.default = [.2 1.3];
+        option.median = median;
+
+            hw.key = 'Halfwave';
+            hw.type = 'Boolean';
+            hw.default = 1;
+        option.hw = hw;                
+        
+        
+%% options related to mirautocor:    
+
+        aut.key = 'Autocor';
+        aut.type = 'Integer';
+        aut.default = 0;
+        aut.keydefault = 1;
+    option.aut = aut;            
+    
+        nw.key = 'NormalWindow';
+        nw.default = 0;
+    option.nw = nw;
+
+        enh.key = 'Enhanced';
+        enh.type = 'Integers';
+        enh.default = 2:10;
+        enh.keydefault = 2:10;
+    option.enh = enh;
+
+        r.key = 'Resonance';
+        r.type = 'String';
+        r.choice = {'ToiviainenSnyder','vanNoorden',0,'off','no'};
+        r.default = 'ToiviainenSnyder';
+    option.r = r;
+
+
+%% options related to mirspectrum:
+    
+        spe.key = 'Spectrum';
+        spe.type = 'Integer';
+        spe.default = 0;
+        spe.keydefault = 1;
+    option.spe = spe;
+
+        zp.key = 'ZeroPad';
+        zp.type = 'Integer';
+        zp.default = 10000;
+        zp.keydefault = Inf;
+    option.zp = zp;
+    
+        prod.key = 'Prod';
+        prod.type = 'Integers';
+        prod.default = 0;
+        prod.keydefault = 2:6;
+    option.prod = prod;
+
+    
+%% options related to the peak detection
+
+        m.key = 'Total';
+        m.type = 'Integer';
+        m.default = 1;
+    option.m = m;
+        
+        thr.key = 'Contrast';
+        thr.type = 'Integer';
+        thr.default = 0.1;
+    option.thr = thr;
+        
+        mi.key = 'Min';
+        mi.type = 'Integer';
+        mi.default = 40;
+    option.mi = mi;
+        
+        ma.key = 'Max';
+        ma.type = 'Integer';
+        ma.default = 200;
+    option.ma = ma;
+
+        track.key = 'Track';
+        track.type = 'Boolean';
+        track.default = 0;
+    option.track = track;
+
+        pref.key = 'Pref';
+        pref.type = 'Integer';
+        pref.number = 2;
+        pref.default = [0 .2];
+    option.pref = pref;
+            
+        perio.key = 'Periodicity';
+        perio.type = 'Boolean';
+        perio.default = 0;
+    option.perio = perio;
+    
+specif.option = option;
+
+varargout = mirfunction(@mirtempo,x,varargin,nargout,specif,@init,@main);
+
+
+%% INIT
+
+function [y type] = init(x,option)
+if iscell(x)
+    x = x{1};
+end
+if option.perio
+    option.m = 3;
+    option.enh = 2:10;
+end
+if not(isamir(x,'mirautocor')) && not(isamir(x,'mirspectrum'))
+    if isframed(x) && strcmpi(option.fea,'Envelope') && not(isamir(x,'mirscalar'))
+        warning('WARNING IN MIRTEMPO: The input should not be already decomposed into frames.');
+        disp(['Suggestion: Use the ''Frame'' option instead.'])
+    end
+    if strcmpi(option.sum,'Before')
+        optionsum = 1;
+    elseif strcmpi(option.sum,'Adjacent')
+        optionsum = 5;
+    else
+        optionsum = 0;
+    end
+    if option.frame.length.val
+        x = mironsets(x,option.fea,'Filterbank',option.fb,...
+                    'FilterbankType',option.fbtype,...
+                    'FilterType',option.ftype,...
+                    'Sum',optionsum,'Method',option.envmeth,...
+                    option.band,'Center',option.c,...
+                    'HalfwaveCenter',option.chwr,'Diff',option.diff,...
+                    'HalfwaveDiff',option.diffhwr,'Lambda',option.lambda,...
+                    'Smooth',option.aver,'Sampling',option.sampling,...
+                    'Complex',option.complex,'Inc',option.inc,...
+                    'Median',option.median(1),option.median(2),...
+                    'Halfwave',option.hw,'Detect',0,...
+                    'Mu',option.mu,'Log',option.log,...
+                    'Frame',option.frame.length.val,...
+                            option.frame.length.unit,...
+                            option.frame.hop.val,...
+                            option.frame.hop.unit);
+    else
+        x = mironsets(x,option.fea,'Filterbank',option.fb,...
+                    'FilterbankType',option.fbtype,...
+                    'FilterType',option.ftype,...
+                    'Sum',optionsum,'Method',option.envmeth,...
+                    option.band,'Center',option.c,...
+                    'HalfwaveCenter',option.chwr,'Diff',option.diff,...
+                    'HalfwaveDiff',option.diffhwr,'Lambda',option.lambda,...
+                    'Smooth',option.aver,'Sampling',option.sampling,...
+                    'Complex',option.complex,'Inc',option.inc,...
+                    'Median',option.median(1),option.median(2),...
+                    'Halfwave',option.hw,'Detect',0,...
+                    'Mu',option.mu,'Log',option.log);
+    end
+end
+if option.aut == 0 && option.spe == 0
+    option.aut = 1;
+end
+if isamir(x,'mirautocor') || (option.aut && not(option.spe))
+    y = mirautocor(x,'Min',60/option.ma,'Max',60/option.mi,...
+          'Enhanced',option.enh,...'NormalInput','coeff',...
+          'Resonance',option.r,'NormalWindow',option.nw);
+elseif isamir(x,'mirspectrum') || (option.spe && not(option.aut))
+    y = mirspectrum(x,'Min',option.mi/60,'Max',option.ma/60,...
+                       'Prod',option.prod,...'NormalInput',...
+                       'ZeroPad',option.zp,'Resonance',option.r);
+elseif option.spe && option.aut
+    ac = mirautocor(x,'Min',60/option.ma,'Max',60/option.mi,...
+          'Enhanced',option.enh,...'NormalInput','coeff',...
+          'Resonance',option.r);
+    sp = mirspectrum(x,'Min',option.mi/60,'Max',option.ma/60,...
+                       'Prod',option.prod,...'NormalInput',...
+                       'ZeroPad',option.zp,'Resonance',option.r);
+    y = ac*sp;
+end
+if ischar(option.sum)
+    y = mirsum(y);
+end
+y = mirpeaks(y,'Total',option.m,'Track',option.track,...
+               'Pref',option.pref(1),option.pref(2),...
+               'Contrast',option.thr,'NoBegin','NoEnd',...
+               'Normalize','Local');
+type = {'mirscalar',mirtype(y)};            
+
+
+%% MAIN
+
+function o = main(p,option,postoption)
+if iscell(p)
+    p = p{1};
+end
+pt = get(p,'TrackPrecisePos');
+track = 1;
+if isempty(pt) || isempty(pt{1})
+    pt = get(p,'PeakPrecisePos');
+    track = 0;
+end
+bpm = cell(1,length(pt));
+for j = 1:length(pt)
+    bpm{j} = cell(1,length(pt{j}));
+    for k = 1:length(pt{j})
+        ptk = pt{j}{k};
+        bpmk = cell(1,size(ptk,2));
+        for h = 1:size(ptk,3)
+            for l = 1:size(ptk,2)
+                ptl = ptk{1,l,h};
+                if isempty(ptl)
+                    bpmk{1,l,h} = NaN;
+                else
+                    if isa(p,'mirautocor') && not(get(p,'FreqDomain'))
+                        bpmk{1,l,h} = 60./ptl;
+                    else
+                        bpmk{1,l,h} = ptl*60;
+                    end
+                end
+            end
+        end
+        if track
+            bpmk = bpmk{1};
+        end
+        bpm{j}{k} = bpmk;
+    end 
+end
+t = mirscalar(p,'Data',bpm,'Title','Tempo','Unit','bpm');
+o = {t,p};
\ No newline at end of file