V_OVERLAPADD join overlapping frames together X=(F,WIN,INC) Usage for frequency-domain processing: S=...; % input signal OV=2; % overlap factor of 2 (4 is also often used) INC=20; % set frame increment in samples NW=INC*OV; % DFT window length W=sqrt(hamming(NW,'periodic')); % omit sqrt if OV=4 W=W/sqrt(sum(W(1:INC:NW).^2)); % normalize window F=v_rfft(v_enframe(S,W,INC),NW,2); % do STFT: one row per time frame, +ve frequencies only ... process frames ... X=v_overlapadd(v_irfft(F,NW,2),W,INC); % reconstitute the time waveform (omit "X=" to plot waveform) Inputs: F(NR,NW) contains the frames to be added together, one frame per row. WIN(NW) contains a window function to multiply each frame. WIN may be omitted to use a default rectangular window If processing the input in chunks, WIN should be replaced by ZI on the second and subsequent calls where ZI is the saved output state from the previous call. INC gives the time increment (in samples) between succesive frames [default = NW]. Outputs: X(N,1) is the output signal. The number of output samples is N=NW+(NR-1)*INC. ZO Contains the saved state to allow a long signal to be processed in chunks. In this case X will contain only N=NR*INC output samples.
0001 function [x,zo]=v_overlapadd(f,win,inc) 0002 %V_OVERLAPADD join overlapping frames together X=(F,WIN,INC) 0003 % 0004 % Usage for frequency-domain processing: 0005 % S=...; % input signal 0006 % OV=2; % overlap factor of 2 (4 is also often used) 0007 % INC=20; % set frame increment in samples 0008 % NW=INC*OV; % DFT window length 0009 % W=sqrt(hamming(NW,'periodic')); % omit sqrt if OV=4 0010 % W=W/sqrt(sum(W(1:INC:NW).^2)); % normalize window 0011 % F=v_rfft(v_enframe(S,W,INC),NW,2); % do STFT: one row per time frame, +ve frequencies only 0012 % ... process frames ... 0013 % X=v_overlapadd(v_irfft(F,NW,2),W,INC); % reconstitute the time waveform (omit "X=" to plot waveform) 0014 % 0015 % Inputs: F(NR,NW) contains the frames to be added together, one 0016 % frame per row. 0017 % WIN(NW) contains a window function to multiply each frame. 0018 % WIN may be omitted to use a default rectangular window 0019 % If processing the input in chunks, WIN should be replaced by 0020 % ZI on the second and subsequent calls where ZI is the saved 0021 % output state from the previous call. 0022 % INC gives the time increment (in samples) between 0023 % succesive frames [default = NW]. 0024 % 0025 % Outputs: X(N,1) is the output signal. The number of output samples is N=NW+(NR-1)*INC. 0026 % ZO Contains the saved state to allow a long signal 0027 % to be processed in chunks. In this case X will contain only N=NR*INC 0028 % output samples. 0029 % 0030 0031 % Copyright (C) Mike Brookes 2009 0032 % Version: $Id: v_overlapadd.m 10865 2018-09-21 17:22:45Z dmb $ 0033 % 0034 % VOICEBOX is a MATLAB toolbox for speech processing. 0035 % Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html 0036 % 0037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0038 % This program is free software; you can redistribute it and/or modify 0039 % it under the terms of the GNU General Public License as published by 0040 % the Free Software Foundation; either version 2 of the License, or 0041 % (at your option) any later version. 0042 % 0043 % This program is distributed in the hope that it will be useful, 0044 % but WITHOUT ANY WARRANTY; without even the implied warranty of 0045 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0046 % GNU General Public License for more details. 0047 % 0048 % You can obtain a copy of the GNU General Public License from 0049 % http://www.gnu.org/copyleft/gpl.html or by writing to 0050 % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. 0051 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0052 [nr,nf]=size(f); % number of frames and frame length 0053 if nargin<2 0054 win=nf; % default increment 0055 end 0056 if isstruct(win) 0057 w=win.w; 0058 if ~numel(w) && length(w)~=nf 0059 error('window length does not match frames size'); 0060 end 0061 inc=win.inc; 0062 xx=win.xx; 0063 else 0064 if nargin<3 0065 inc=nf; 0066 end 0067 if numel(win)==1 && win==fix(win) && nargin<3 % win has been omitted 0068 inc=win; 0069 w=[]; 0070 else 0071 w=win(:).'; 0072 if length(w)~=nf 0073 error('window length does not match frames size'); 0074 end 0075 if all(w==1) 0076 w=[]; 0077 end 0078 end 0079 xx=[]; % partial output from previous call is null 0080 end 0081 nb=ceil(nf/inc); % number of overlap buffers 0082 no=nf+(nr-1)*inc; % buffer length 0083 z=zeros(no,nb); % space for overlapped output speech 0084 if numel(w) 0085 z(repmat(1:nf,nr,1)+repmat((0:nr-1)'*inc+rem((0:nr-1)',nb)*no,1,nf))=f.*repmat(w,nr,1); 0086 else 0087 z(repmat(1:nf,nr,1)+repmat((0:nr-1)'*inc+rem((0:nr-1)',nb)*no,1,nf))=f; 0088 end 0089 x=sum(z,2); 0090 if ~isempty(xx) 0091 x(1:length(xx))=x(1:length(xx))+xx; % add on leftovers from previous call 0092 end 0093 if nargout>1 % check if we want to preserve the state 0094 mo=inc*nr; % completed output samples 0095 if no<mo 0096 x(mo,1)=0; 0097 zo.xx=[]; 0098 else 0099 zo.xx=x(mo+1:end); 0100 zo.w=w; 0101 zo.inc=inc; 0102 x=x(1:mo); 0103 end 0104 elseif ~nargout 0105 if isempty(xx) 0106 k1=nf-inc; % dubious samples at start 0107 else 0108 k1=0; 0109 end 0110 k2=nf-inc; % dubious samples at end 0111 plot(1+(0:nr-1)*inc,x(1+(0:nr-1)*inc),'>r',nf+(0:nr-1)*inc,x(nf+(0:nr-1)*inc),'<r', ... 0112 1:k1+1,x(1:k1+1),':b',k1+1:no-k2,x(k1+1:end-k2),'-b',no-k2:no,x(no-k2:no),':b'); 0113 xlabel('Sample Number'); 0114 title(sprintf('%d frames of %d samples with %.0f%% overlap = %d samples',nr,nf,100*(1-inc/nf),no)); 0115 end