


FINDPEAKS finds peaks with optional quadratic interpolation [K,V]=(X,M,W)
Inputs: X is the input signal (does not work with UInt datatype)
M is mode:
'q' performs quadratic interpolation
'v' finds valleys instead of peaks
W is the width tolerance; a peak will be eliminated if there is
a higher peak within +-W samples
Outputs: K are the peak locations in X (fractional if M='q')
V are the peak amplitudes: if M='q' the amplitudes will be interpolated
whereas if M~='q' then V=X(K).

0001 function [k,v]=findpeaks(x,m,w) 0002 %FINDPEAKS finds peaks with optional quadratic interpolation [K,V]=(X,M,W) 0003 % 0004 % Inputs: X is the input signal (does not work with UInt datatype) 0005 % M is mode: 0006 % 'q' performs quadratic interpolation 0007 % 'v' finds valleys instead of peaks 0008 % W is the width tolerance; a peak will be eliminated if there is 0009 % a higher peak within +-W samples 0010 % 0011 % Outputs: K are the peak locations in X (fractional if M='q') 0012 % V are the peak amplitudes: if M='q' the amplitudes will be interpolated 0013 % whereas if M~='q' then V=X(K). 0014 0015 % Outputs are column vectors regardless of whether X is row or column. 0016 % If there is a plateau rather than a sharp peak, the routine will place the 0017 % peak in the centre of the plateau. When the W input argument is specified, 0018 % the routine will eliminate the lower of any pair of peaks whose separation 0019 % is <=W; if the peaks have exactly the same height, the second one will be eliminated. 0020 % All peak locations satisfy 1<K<length(X). 0021 % 0022 % If no output arguments are specified, the results will be plotted. 0023 % 0024 0025 % Copyright (C) Mike Brookes 2005 0026 % Version: $Id: findpeaks.m 713 2011-10-16 14:45:43Z dmb $ 0027 % 0028 % VOICEBOX is a MATLAB toolbox for speech processing. 0029 % Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html 0030 % 0031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0032 % This program is free software; you can redistribute it and/or modify 0033 % it under the terms of the GNU General Public License as published by 0034 % the Free Software Foundation; either version 2 of the License, or 0035 % (at your option) any later version. 0036 % 0037 % This program is distributed in the hope that it will be useful, 0038 % but WITHOUT ANY WARRANTY; without even the implied warranty of 0039 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0040 % GNU General Public License for more details. 0041 % 0042 % You can obtain a copy of the GNU General Public License from 0043 % http://www.gnu.org/copyleft/gpl.html or by writing to 0044 % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. 0045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0046 0047 if nargin<2 0048 m=' '; 0049 end 0050 nx=length(x); 0051 if any(m=='v') 0052 x=-x(:); % invert x if searching for valleys 0053 else 0054 x=x(:); % force to be a column vector 0055 end 0056 dx=x(2:end)-x(1:end-1); 0057 r=find(dx>0); 0058 f=find(dx<0); 0059 0060 if length(r)>0 & length(f)>0 % we must have at least one rise and one fall 0061 dr=r; 0062 dr(2:end)=r(2:end)-r(1:end-1); 0063 rc=repmat(1,nx,1); 0064 rc(r+1)=1-dr; 0065 rc(1)=0; 0066 rs=cumsum(rc); % = time since the last rise 0067 0068 df=f; 0069 df(2:end)=f(2:end)-f(1:end-1); 0070 fc=repmat(1,nx,1); 0071 fc(f+1)=1-df; 0072 fc(1)=0; 0073 fs=cumsum(fc); % = time since the last fall 0074 0075 rp=repmat(-1,nx,1); 0076 rp([1; r+1])=[dr-1; nx-r(end)-1]; 0077 rq=cumsum(rp); % = time to the next rise 0078 0079 fp=repmat(-1,nx,1); 0080 fp([1; f+1])=[df-1; nx-f(end)-1]; 0081 fq=cumsum(fp); % = time to the next fall 0082 0083 k=find((rs<fs) & (fq<rq) & (floor((fq-rs)/2)==0)); % the final term centres peaks within a plateau 0084 v=x(k); 0085 0086 if any(m=='q') % do quadratic interpolation 0087 b=0.5*(x(k+1)-x(k-1)); 0088 a=x(k)-b-x(k-1); 0089 j=(a>0); % j=0 on a plateau 0090 v(j)=x(k(j))+0.25*b(j).^2./a(j); 0091 k(j)=k(j)+0.5*b(j)./a(j); 0092 k(~j)=k(~j)+(fq(k(~j))-rs(k(~j)))/2; % add 0.5 to k if plateau has an even width 0093 end 0094 0095 % now purge nearby peaks 0096 0097 if nargin>2 0098 j=find(k(2:end)-k(1:end-1)<=w); 0099 while any(j) 0100 j=j+(v(j)>=v(j+1)); 0101 k(j)=[]; 0102 v(j)=[]; 0103 j=find(k(2:end)-k(1:end-1)<=w); 0104 end 0105 end 0106 else 0107 k=[]; 0108 v=[]; 0109 end 0110 if any(m=='v') 0111 v=-v; % invert peaks if searching for valleys 0112 end 0113 if ~nargout 0114 if any(m=='v') 0115 x=-x; % re-invert x if searching for valleys 0116 ch='v'; 0117 else 0118 ch='^'; 0119 end 0120 plot(1:nx,x,'-',k,v,ch); 0121 end