function [X,opix] = ola(Y,H) % X = ola(Y,H) % Overlap-add columns of Y, offset by H. % There's no windowing (i.e. scaling by a tapered window) in here. % 2010-11-14 Dan Ellis dpwe@ee.columbia.edu [W,nw] = size(Y); % How long should X be in the end? % one complete window, plus another hop's worth of points for each % additional window lenx = (W + (nw-1)*H); % The approach is to build an index matrix, where each row pulls % in successive, nonoverlapping windows from the original data. % This matrix then has as many rows as needed to get all the % overlapping windows. We can then index the input with it, and % simply sum up. % Upper bound on the the number of windows that overlap for each % point = the number of rows we'll need in our index matrix ovf = ceil(W/H); % How many windows will there be in each row? nwonf = ceil(nw/ovf); % Unravel Y, then add a zero on the end. Any indices we don't need % in our index will point here, so they have no contribution to the % final sum Ywz = [Y(:)',0]; % (index for the final zero value) leny = length(Ywz); % Here's the indexing magic. Create one row of the final index % matrix that pulls out every ovf'th window from the original % matrix in its unravelled form. Pad any gaps with the zero index. opix = reshape(repmat([[1:W],leny*ones(1,ovf*H - W)]', 1, nwonf) ... + repmat(ovf*W*[0:(nwonf-1)], ovf*H, 1), ... 1, ovf*H*nwonf); % need to pad out opix to cover hangover of final window opix = [opix,leny*ones(1,lenx-length(opix))]; lopix = length(opix); % Add in the following rows, which are offset by H points, and with % indices that are shifted to pick up the interleaving windows for i = 2:ovf opix = [opix;[leny*ones(1,(i-1)*H),W+opix(1,1:(lopix-(i-1)*H))]]; end % Any points off the end get set to the zero value opix(opix > leny) = leny; % Now, the big payoff - index by the rows, including pulling in the % zeros, in such a way that it's all ready to sum up to get OLA X = sum(Ywz(opix))';