changeset 4:e23a23349e31

Added inverse transform
author danieleb@code.soundsoftware.ac.uk
date Thu, 16 Jun 2011 13:16:29 +0100
parents ee2a86d7ec07
children 084000643ad1
files dcti.m idcti.m ilot.m invlappedorthotransform.m l1overl2.m lappedorthobasis.m lappedorthotransform.m lappedwindow.m lot.m
diffstat 9 files changed, 342 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
--- a/dcti.m	Wed Jun 15 11:26:03 2011 +0100
+++ b/dcti.m	Thu Jun 16 13:16:29 2011 +0100
@@ -14,14 +14,14 @@
 % c: vector or matrix contaning the dct coefficients
 %
 % REFERENCES
-%   1)
+% 1)
 %
 % SEE ALSO
 % DCT, FFT, IDCT, IFFT
 
-%   Author(s): Daniele Barchiesi
-%   Copyright QMUL
-%   $Revision: 1
+% Author(s): Daniele Barchiesi
+% Copyright QMUL
+% $Revision: 1
 
 
 %% Check inputs & defaults
--- a/idcti.m	Wed Jun 15 11:26:03 2011 +0100
+++ b/idcti.m	Thu Jun 16 13:16:29 2011 +0100
@@ -14,14 +14,14 @@
 % c: vector or matrix contaning the inverse dct coefficients
 %
 % REFERENCES
-%   1)
+% 1)
 %
 % SEE ALSO
 % DCTI, DCT, IDCT
 
-%   Author(s): Daniele Barchiesi
-%   Copyright QMUL
-%   $Revision: 1
+% Author(s): Daniele Barchiesi
+% Copyright QMUL
+% $Revision: 1
 
 
 %% Check inputs & defaults
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ilot.m	Thu Jun 16 13:16:29 2011 +0100
@@ -0,0 +1,131 @@
+function x = ilot(y,wLength,orthoBasis,tailLength,tailFunc)
+%INVLAPPEDORTHOTRANSFORM Inverse lapped orthogonal transform
+%
+% USAGE
+% x = lappedorthotransform(y,wLength,orthoBasis,tailLength,tailFunc)
+%
+% INPUT:
+% y: vector or matrix containing the LOT coefficients. If matrix,
+% the function acts columnwise.
+%
+% wLength: scalar or vector containing the lengths of the overlapping
+% windows (if vector, the sum of wLength must equal the length of y)
+%
+% orthobasis: (optional, default='mdct') either a string or a function
+% handle corresponding to an orhogonal transform to be used in each
+% overlapping window.
+%
+% tailLength: (optional, default=floor(min(wLength)/2)) length of the tail
+% of the overlapping windows. Two consecutive windows overlap in a interval
+% of dimension 2*tailLength. The maximum tailLength cannot exceed half the
+% length of the smallest window.
+%
+% tailFunc: (optional, default='sin2') either a string or a function handle
+% used to define the tails of the overlapping windows (see LAPPEDWINDOW for
+% more details).
+%
+% OUTPUT:
+% x: vector or matrix of coefficients of the inverse LOT.
+%
+% REFERENCES:
+% S. Mallat, A Wavelet Tour of Signal Processing
+%
+% SEE ALSO
+% LAPPEDORTHOBASIS, LAPPEDWINDOW, LAPPEDORTHOTRANSFORM
+
+% Author(s): Daniele Barchiesi
+% Copyright QMUL
+% $Revision: 1
+
+%% Check input & defaults
+error(nargchk(2, 5, nargin, 'struct'));
+
+if isscalar(wLength) %create vector of fixed window lengths
+    nWindows = floor(length(y)/wLength);
+    wLength = wLength*ones(nWindows,1);
+end
+
+if ~exist('orthoBasis','var') || isempty(orthoBasis), orthoBasis = 'mdct'; end
+if ~exist('tailFunc','var')   || isempty(tailFunc), tailFunc = 'sin2'; end
+if ~exist('tailLength','var') || isempty(tailLength)
+    tailLength = floor(min(wLength)/2);
+end
+
+% check wLength
+if length(y)<sum(wLength), error('you must pad the signal!'); end
+% define function handle to the forward local transform
+if ischar(orthoBasis)
+    switch orthoBasis
+        case 'mdct'
+            invOrthoFun = @(y) idcti(y,'IV');
+        otherwise
+            error('invalid basis function');
+    end
+elseif isa(orthoBasis,'function_handle')
+    invOrthoFun = orthoBasis;
+else
+    error('invalid basis function');
+end
+
+%% Matrix case: act columnwise
+if size(y,2)>1
+    x = zeros(size(y));
+    for iCol=1:size(y,2)
+        x(:,iCol) = invlappedorthotransform(y(:,iCol),wLength,orthoBasis,...
+            tailLength,tailFunc);
+    end
+    return
+end
+
+%% Compute transform
+nWindows  = length(wLength);
+sigLength = sum(wLength);
+x         = zeros(sigLength,1);
+
+% first frame
+g = lappedwindow(wLength(1),tailLength,tailFunc,'first');
+h = invOrthoFun(y(1:wLength(1))); % folded ilot
+C = 1:wLength(1)-tailLength;      % central interval
+Om = wLength(1)-tailLength+(1:tailLength);  %overlapping interval (end)
+hp = invOrthoFun(y(wLength(1)+(1:wLength(2)))); % next folded ilot
+x(C) = h(C);
+% unfold
+x(Om) = g(Om).*h(Om) + g(end:-1:end-tailLength+1).*hp(tailLength:-1:1);
+
+% central frames
+for p=2:nWindows-1
+    hm = h; % previous folded ilot
+    h = hp; % current folded ilot
+    % next folded ilot
+    if strcmpi(orthoBasis,'mdct') && p==nWindows-1 % if mdct use idct I
+        hp = idcti(y(sum(wLength(1:end-1))+(1:wLength(end))),'I');
+    else
+        hp = invOrthoFun(y(sum(wLength(1:end-1))+(1:wLength(end))));
+    end
+    g = lappedwindow(wLength(p),tailLength,tailFunc);
+    % overlapping interval (start)
+    Op = sum(wLength(1:p-1))+(1:tailLength);
+    % central interval
+    C  = sum(wLength(1:p-1))+(tailLength+1:wLength(p)-tailLength);
+    % overlapping interval (end)
+    Om = sum(wLength(1:p-1))+ wLength(p)-tailLength+(1:tailLength);
+    % unfold
+    x(Op) = g(tailLength+(1:tailLength)).*h(1:tailLength) - ...
+        g(tailLength:-1:1).*hm(end:-1:end-tailLength+1);
+    x(C) = h(tailLength+1:wLength(p)-tailLength);
+    x(Om) = g(wLength(p)+(1:tailLength)).*h(wLength(p)-tailLength+(1:tailLength)) + ...
+        g(end:-1:end-tailLength+1).*hp(tailLength:-1:1);
+end
+
+%last frame
+hm = h; % previous folded ilot
+h = hp; % current folded ilot
+g = lappedwindow(wLength(end),tailLength,tailFunc);
+% overlapping interval (start)
+Op = sum(wLength(1:end-1))+(1:tailLength);
+% central interval
+C  = sum(wLength(1:end-1))+(tailLength+1:wLength(end));
+% unfold
+x(Op) = g(tailLength+(1:tailLength)).*h(1:tailLength) - ...
+        g(tailLength:-1:1).*hm(end:-1:end-tailLength+1);
+x(C) = h(tailLength+1:end);
--- a/invlappedorthotransform.m	Wed Jun 15 11:26:03 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-function x = invlappedorthotransform(y,wLength,orthoBasis,tailLength,tailFunc)
-%>INVLAPPEDORTHOTRANSFORM Inverse lapped orthogonal transform (iLOT)
-%>
-%> x = lappedorthotransform(y,wLength,orthoBasis,tailLength,tailFunc)
-%>
-%> returns the inverse lapped orthogonal transform of the signal y 
-%>
-%> INPUT:
-%> - y: vector containing the LOT
-%> - wLength: vector containing the lengths of the overlapping windows (the
-%> sum of wLength must equal the length of x)
-%> - orthobasis: either a string or a function handle corresponding to an
-%> orhogonal transform to be used in each overlapping window. The default
-%> is DCT-IV (which is globally referred as MDCT)
-%> - tailLength: length of the tail of the overlapping windows. Two
-%> consecutive windows overlap in a portion of dimension 2*tailLength. 
-%> The maximum tailLength cannot exceed half the length of the smallest 
-%> window. 
-%> - tailFunc: either a string or a function handle used to define the tails
-%> of the overlapping windows. The default is 'sin2' (twicely differentiable
-%> sinusoidal).
-%>
-%> OUTPUT:
-%> - x: inverse LOT
-%>
-%> REFERENCE:
-%> S. Mallat, A Wavelet Tour of Signal Processing
-%>
-%> SEE ALSO
-%> lappedorthobasis, lappedwindow
-%>
-%> ----------------------------------------------------------- %
-%>  Daniele Barchiesi, daniele.barchiesi@eecs.qmul.ac.uk       %
-%>  Centre for Digital Music, Queen Mary University of London  %
-%>  May 2011                                                  %
-%> ----------------------------------------------------------- %
-%%> Check input & defaults
-error(nargchk(2, 5, nargin, 'struct'));
-if ~exist('orthoBasis','var') || isempty(orthoBasis), orthoBasis = 'mdct'; end
-if ~exist('tailFunc','var')   || isempty(tailFunc), tailFunc = 'sin2'; end
-if ~exist('tailLength','var') || isempty(tailLength)
-    tailLength = floor(min(wLength)/2); 
-end
-if length(x)<sum(wLength), error('you must pad the signal!'); end
-
-if ischar(orthoBasis)
-    switch orthoBasis
-        case 'mdct'
-            orthoFun = @(x) dcti(x,'IV');
-        otherwise
-            error('invalid basis function');
-    end
-elseif isa(orthoBasis,'function_handle')
-    orthoFun = orthoBasis;
-else
-    error('invalid basis function');
-end
-
-%%> Compute transform
--- a/l1overl2.m	Wed Jun 15 11:26:03 2011 +0100
+++ b/l1overl2.m	Thu Jun 16 13:16:29 2011 +0100
@@ -1,33 +1,27 @@
 function z = l1overl2(X)
-%L1OVERL2 ratio between the l1 and the l2 norms.
+%L1OVERL2 ratio between l1 and l2 norm
 %
-% z = l1overl2(X)
+% USAGE
+% z = l1overl2(x)
 %
-% computes the ratio between the l1 and the l2 norm of the input X. If
-% input is a matrix, the norms are calculated along the columns and a mean
-% value is returned. If the input is a cell, the norms are calculated
-% independently for each cell entry and a mean value is returned.
+% INPUT
+% x: input vector or matrix. If matrix, the function acts columnwise
+% returning one value for each column.
 %
-% ----------------------------------------------------------- %
-%  Daniele Barchiesi, daniele.barchiesi@eecs.qmul.ac.uk       %
-%  Centre for Digital Music, Queen Mary University of London  %
-%  Apr. 2011                                                  %
-% ----------------------------------------------------------- %
-if iscell(X)
-    nCols = length(X);
-    z = zeros(nCols,1);
-    for i=1:nCols
-        z(i) = norm(X{:,i},1)/norm(X{:,i},2);
-    end
-else
-    nCols = size(X,2);
-    z = zeros(nCols,1);
-    for i=1:nCols
-        z(i) = norm(X(:,i),1)/norm(X(:,i),2);
-    end
+% OUTPUT
+% z: the ratio ||x||_1/||x||_2
+%
+% SEE ALSO
+% NORM
+
+% Author(s): Daniele Barchiesi
+% Copyright QMUL
+% $Revision: 1
+
+nCols = size(X,2);
+z = zeros(nCols,1);
+for i=1:nCols
+    z(i) = norm(X(:,i),1)/norm(X(:,i),2);
 end
 
-z(isnan(z)) = [];
-z = mean(z);
-
 %EOF
\ No newline at end of file
--- a/lappedorthobasis.m	Wed Jun 15 11:26:03 2011 +0100
+++ b/lappedorthobasis.m	Thu Jun 16 13:16:29 2011 +0100
@@ -60,41 +60,56 @@
 suppLen   = @(p) wLength(p)+2*tailLength;
 
 % first frame
+% generate window
 g = lappedwindow(wLength(1),tailLength,tailFunc,'first');
+% generate local orthogonal matrix
 orthoMat = basisFun(eye(wLength(1)));
+% periodically extend length of basis functions to overlapping regions
 orthoMatExtended = orthomatextend(orthoMat,tailLength,'first');
+% multiply local orthogonal matrix by windowing function
 phi(1:wLength(1)+tailLength,1:wLength(1)) = diag(sparse(g))*orthoMatExtended;
 
 % central frames
 for p=2:nWindows-1
+    % generate window
     g = lappedwindow(wLength(p),tailLength,tailFunc);
+    % generate local orthogonal matrix
     orthoMat = basisFun(eye(wLength(p)));
+    % periodically extend length of basis functions to overlapping regions
     orthoMatExtended = orthomatextend(orthoMat,tailLength);
+    % multiply local orthogonal matrix by windowing function
     phi(sum(wLength(1:p-1))-tailLength+(1:suppLen(p)),sum(wLength(1:p-1))+(1:wLength(p)))...
         = diag(sparse(g))*orthoMatExtended;
 end
 
 %last frame
+% generate window
 g = lappedwindow(wLength(end),tailLength,tailFunc,'last');
-if strcmpi(orthobasis,'mdct')
+% generate local orthogonal matrix
+if strcmpi(orthobasis,'mdct') %if mdct use dct I at last block to avoid artefacts
     orthoMat = dcti(eye(wLength(end)),'I');
 else
     orthoMat = basisFun(eye(wLength(end)));
 end
+% periodically extend length of basis functions to overlapping regions
 orthoMatExtended = orthomatextend(orthoMat,tailLength,'last');
+% multiply local orthogonal matrix by windowing function
 phi(sum(wLength(1:end-1))-tailLength+(1:wLength(end)+tailLength),sum(wLength(1:end-1))+(1:wLength(end)))...
     = diag(sparse(g))*orthoMatExtended;
 
 function orthomatextended = orthomatextend(orthomat,tailLength,special)
 % Periodic extension of local orthonormal basis
-
-if ~exist('special','var') || isempty(special), special = []; end 
+if ~exist('special','var') || isempty(special), special = []; end
 
 if strcmpi(special,'first')
+    % odd symmetry at the end of basis functions
     orthomatextended = [orthomat; -orthomat(end:-1:end-tailLength+1,:)];
 elseif strcmpi(special,'last')
+    % even symmetry at the beginning of basis functions
     orthomatextended = [flipud(orthomat(1:tailLength,:)); orthomat];
 else
+    % even symmetry at the beginning and odd symmetry at the end of basis
+    % functions
     orthomatextended = [flipud(orthomat(1:tailLength,:)); orthomat; ...
         -orthomat(end:-1:end-tailLength+1,:)];
 end
\ No newline at end of file
--- a/lappedorthotransform.m	Wed Jun 15 11:26:03 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-function y = lappedorthotransform(x,wLength,orthoBasis,tailLength,tailFunc)
-%LAPPEDORTHOTRANSFORM Lapped orthogonal transform
-%
-% y = lappedorthotransform(x,wLength,orthoBasis,tailLength,tailFunc)
-%
-% returns the lapped orthogonal transform of the signal x 
-%
-% INPUT:
-% - x: vector containing the input signal 
-% - wLength: vector containing the lengths of the overlapping windows (the
-% sum of wLength must equal the length of x)
-% - orthobasis: either a string or a function handle corresponding to an
-% orhogonal transform to be used in each overlapping window. The default
-% is DCT-IV (which is globally referred as MDCT)
-% - tailLength: length of the tail of the overlapping windows. Two
-% consecutive windows overlap in a portion of dimension 2*tailLength. 
-% The maximum tailLength cannot exceed half the length of the smallest 
-% window. 
-% - tailFunc: either a string or a function handle used to define the tails
-% of the overlapping windows. The default is 'sin2' (twicely differentiable
-% sinusoidal).
-%
-% OUTPUT:
-% - y: vector of coefficients of the lapped orthogonal transform
-%
-% REFERENCE:
-% S. Mallat, A Wavelet Tour of Signal Processing
-%
-% SEE ALSO
-% lappedorthobasis, lappedwindow
-%
-% ----------------------------------------------------------- %
-%  Daniele Barchiesi, daniele.barchiesi@eecs.qmul.ac.uk       %
-%  Centre for Digital Music, Queen Mary University of London  %
-%  Apr. 2011                                                  %
-% ----------------------------------------------------------- %
-%% Check input & defaults
-error(nargchk(2, 5, nargin, 'struct'));
-if ~exist('orthoBasis','var') || isempty(orthoBasis), orthoBasis = 'mdct'; end
-if ~exist('tailFunc','var')   || isempty(tailFunc), tailFunc = 'sin2'; end
-if ~exist('tailLength','var') || isempty(tailLength)
-    tailLength = floor(min(wLength)/2); 
-end
-if isscalar(wLength)
-    nWindows = floor(length(x)/wLength);
-    wLength = wLength*ones(nWindows,1);
-end
-if length(x)<sum(wLength), error('you must pad the signal!'); end
-if ischar(orthoBasis)
-    switch orthoBasis
-        case 'mdct'
-            orthoFun = @(x) dcti(x,'IV');
-        otherwise
-            error('invalid basis function');
-    end
-elseif isa(orthoBasis,'function_handle')
-    orthoFun = orthoBasis;
-else
-    error('invalid basis function');
-end
-
-%% Compute transform
-nWindows  = length(wLength);
-sigLength = sum(wLength);
-y         = zeros(sigLength,1);
-suppLen   = @(p) wLength(p)+2*tailLength;
-
-% first frame
-h = lappedprojector(x(1:wLength(1)+tailLength),wLength(1),tailLength,tailFunc,'first');
-y(1:wLength(1)) = orthoFun(h(1:wLength(1)));
-
-% central frames
-for p=2:nWindows-1
-    h = lappedprojector(x(sum(wLength(1:p-1))-tailLength+(1:suppLen(p))),...
-        wLength(p),tailLength,tailFunc);
-    y(sum(wLength(1:p-1))+(1:wLength(p))) = orthoFun(h(tailLength+(1:wLength(p))));
-end
-    
-%last frame
-h = lappedprojector(x(sum(wLength(1:end-1))-tailLength+(1:wLength(end)+tailLength)),...
-    wLength(end),tailLength,tailFunc,'last');
-if strcmpi(orthoBasis,'mdct')
-    y(sum(wLength(1:end-1))+(1:wLength(end))) = dcti(h(tailLength+(1:wLength(end))),'I');
-else
-    y(sum(wLength(1:end-1))+(1:wLength(end))) = orthoFun(h(tailLength+(1:wLength(end))));
-end
-
-function h = lappedprojector(f,wLength,tailLength,tailFunc,special)
-% Projects the input f into the space of functions with support contained
-% in the interval defined by the lapped window defined according to the
-% input parameteres
-
-% check inputs
-error(nargchk(2, 5, nargin, 'struct'));
-if ~exist('special','var') || isempty(special), special = []; end
-if ~exist('tailFunx','var') || isempty(tailFunc), tailFunc = 'sin2'; end
-if ~exist('tailLength','var') || isempty(tailLength)
-    tailLength = floor(min(wLength)/2);
-end
-
-% generate the window and project
-g = lappedwindow(wLength,tailLength,tailFunc,special);
-h = f;
-if ~isempty(special)
-    if strcmpi(special,'first')
-        O = wLength-tailLength+(1:2*tailLength);
-        h(O) = g(O).*f(O) - g(fliplr(O)).*f(fliplr(O));
-    elseif strcmpi(special,'last')
-        O = 1:2*tailLength;
-        h(O) = g(O).*f(O) + g(fliplr(O)).*f(fliplr(O));
-    end
-else
-    Os = 1:2*tailLength;
-    Oe = wLength+(1:2*tailLength);
-    h(Os) = g(Os).*f(Os) + g(fliplr(Os)).*f(fliplr(Os));
-    h(Oe) = g(Oe).*f(Oe) - g(fliplr(Oe)).*f(fliplr(Oe));
-end
\ No newline at end of file
--- a/lappedwindow.m	Wed Jun 15 11:26:03 2011 +0100
+++ b/lappedwindow.m	Thu Jun 16 13:16:29 2011 +0100
@@ -1,13 +1,13 @@
 function g = lappedwindow(wLength,tailLength,tailFunc,special)
-%LAPPEDWINDOW Lapped window used for lapped orthogonal transform
+%LAPPEDWINDOW Lapped window for lapped orthogonal transform
 %
+% USAGE
 % g = lappedwindow(wLength,tailLength,tailFunc,special)
 %
-% returns the window g used in the lapped orthogonal transform
-%
 % INPUT:
 % - wLength: length of the window
-% - tailLength: length of the tail of the overlapping window. 
+% - tailLength: (optional, default=floor(wLength/2))length of the tail of 
+% the overlapping window. 
 %
 %     ......................
 %   |.                      .|
@@ -18,9 +18,9 @@
 %                         tailLength
 %
 % The maximum tailLength cannot exceed half the window length. 
-% - tailFunc: either a string or a function handle used to define the tails
-% of the overlapping windows. The default is 'sin2' (twicely differentiable
-% sinusoidal).
+% - tailFunc: (optional, default='sin2') either a string or a function 
+% handle used to define the tails of the overlapping windows. The default 
+% is 'sin2' (twicely differentiable sinusoidal).
 %
 % OUTPUT:
 % - g: vector containing the window
@@ -31,16 +31,16 @@
 % SEE ALSO
 % lappedorthobasis, lappedorthotransform
 %
-% ----------------------------------------------------------- %
-%  Daniele Barchiesi, daniele.barchiesi@eecs.qmul.ac.uk       %
-%  Centre for Digital Music, Queen Mary University of London  %
-%  Apr. 2011                                                  %
-% ----------------------------------------------------------- %
+
+% Author(s): Daniele Barchiesi
+% Copyright QMUL
+% $Revision: 1
 
 %% Check inputs
-error(nargchk(2, 4, nargin, 'struct'));
+error(nargchk(1, 4, nargin, 'struct'));
 if ~exist('special','var') || isempty(special), special = []; end
-if ~exist('tailFunx','var') || isempty(tailFunc), tailFunc = 'sin2'; end
+if ~exist('tailFunc','var') || isempty(tailFunc), tailFunc = 'sin2'; end
+if ~exist('tailLength','var') || isempty(tailLength), tailLength = floor(wLength/2); end
 
 %check that the window is not too short
 if wLength<2*tailLength
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lot.m	Thu Jun 16 13:16:29 2011 +0100
@@ -0,0 +1,151 @@
+function y = lot(x,wLength,orthoBasis,tailLength,tailFunc)
+%LAPPEDORTHOTRANSFORM Lapped orthogonal transform
+%
+% USAGE
+% y = lappedorthotransform(x,wLength,orthoBasis,tailLength,tailFunc)
+%
+% INPUT:
+% x: vector or matrix containing the input signal. If matrix, the function 
+% acts columnwise.
+%
+% wLength: scalar or vector containing the lengths of the overlapping
+% windows (if vector, the sum of wLength must equal the length of x)
+% 
+% orthobasis: (optional, default='mdct') either a string or a function
+% handle corresponding to an orhogonal transform to be used in each 
+% overlapping window.
+% 
+% tailLength: (optional, default=floor(min(wLength)/2)) length of the tail
+% of the overlapping windows. Two consecutive windows overlap in a portion
+% of dimension 2*tailLength. The maximum tailLength cannot exceed half the 
+% length of the smallest window. 
+% 
+% tailFunc: (optional, default='sin2') either a string or a function handle
+% used to define the tails of the overlapping windows (see LAPPEDWINDOW for
+% more details).
+%
+% OUTPUT:
+% y: vector or matrix of coefficients of the lapped orthogonal transform.
+%
+% REFERENCES:
+% S. Mallat, A Wavelet Tour of Signal Processing
+%
+% SEE ALSO
+% LAPPEDORTHOBASIS, LAPPEDWINDOW, INVLAPPEDORTHOTRANSFORM
+
+% Author(s): Daniele Barchiesi
+% Copyright QMUL
+% $Revision: 1
+
+%% Check input & defaults
+error(nargchk(2, 5, nargin, 'struct'));
+
+if isscalar(wLength) %create vector of fixed window lengths
+    nWindows = floor(length(x)/wLength);
+    wLength = wLength*ones(nWindows,1);
+end
+
+if ~exist('orthoBasis','var') || isempty(orthoBasis), orthoBasis = 'mdct'; end
+if ~exist('tailFunc','var')   || isempty(tailFunc), tailFunc = 'sin2'; end
+if ~exist('tailLength','var') || isempty(tailLength)
+    tailLength = floor(min(wLength)/2); 
+end
+
+% check wLength
+if length(x)<sum(wLength), error('you must pad the signal!'); end
+% define function handle to the forward local transform
+if ischar(orthoBasis)
+    switch orthoBasis
+        case 'mdct'
+            orthoFun = @(x) dcti(x,'IV');
+        otherwise
+            error('invalid basis function');
+    end
+elseif isa(orthoBasis,'function_handle')
+    orthoFun = orthoBasis;
+else
+    error('invalid basis function');
+end
+
+%% Matrix case: act columnwise
+if size(x,2)>1
+    y = zeros(size(x));
+    for iCol=1:size(x,2)
+        y(:,iCol) = lappedorthotransform(x(:,iCol),wLength,orthoBasis,...
+            tailLength,tailFunc);
+    end
+    return
+end
+
+%% Compute transform
+nWindows  = length(wLength);
+sigLength = sum(wLength);
+y         = zeros(sigLength,1);
+% length of the support of the p-th window
+suppLen   = @(p) wLength(p)+2*tailLength;
+
+% first frame
+% project input signal onto orthogonal subspace associated with the first
+% window
+h = lappedprojector(x(1:wLength(1)+tailLength),wLength(1),tailLength,tailFunc,'first');
+% transform projected signal 
+y(1:wLength(1)) = orthoFun(h(1:wLength(1)));
+
+% central frames
+for p=2:nWindows-1
+    % project input signal onto orthogonal subspace associated with the
+    % p-th window
+    h = lappedprojector(x(sum(wLength(1:p-1))-tailLength+(1:suppLen(p))),...
+        wLength(p),tailLength,tailFunc);
+    % transform projected signal
+    y(sum(wLength(1:p-1))+(1:wLength(p))) = orthoFun(h(tailLength+(1:wLength(p))));
+end
+    
+%last frame
+% project input signal onto orthogonal subspace associated with the
+% last window
+h = lappedprojector(x(sum(wLength(1:end-1))-tailLength+(1:wLength(end)+tailLength)),...
+    wLength(end),tailLength,tailFunc,'last');
+% transform projected signal
+if strcmpi(orthoBasis,'mdct') %id mdct use DCT I at last frame to avoid artefacts
+    y(sum(wLength(1:end-1))+(1:wLength(end))) = dcti(h(tailLength+(1:wLength(end))),'I');
+else
+    y(sum(wLength(1:end-1))+(1:wLength(end))) = orthoFun(h(tailLength+(1:wLength(end))));
+end
+
+function h = lappedprojector(f,wLength,tailLength,tailFunc,special)
+% Projects the input f into the space of functions with support contained
+% in the interval defined by the lapped window.
+
+% check inputs
+error(nargchk(2, 5, nargin, 'struct'));
+if ~exist('special','var') || isempty(special), special = []; end
+if ~exist('tailFunc','var') || isempty(tailFunc), tailFunc = 'sin2'; end
+if ~exist('tailLength','var') || isempty(tailLength)
+    tailLength = floor(min(wLength)/2);
+end
+
+% generate the window and project
+g = lappedwindow(wLength,tailLength,tailFunc,special);
+h = f;
+if ~isempty(special)
+    if strcmpi(special,'first')
+        % overlapping region
+        O = wLength-tailLength+(1:2*tailLength);
+        % project
+        h(O) = g(O).*f(O) - g(fliplr(O)).*f(fliplr(O));
+    elseif strcmpi(special,'last')
+        % overlapping portion
+        O = 1:2*tailLength;
+        % project
+        h(O) = g(O).*f(O) + g(fliplr(O)).*f(fliplr(O));
+    end
+else
+    % start overlapping region
+    Os = 1:2*tailLength;
+    % end overlapping region
+    Oe = wLength+(1:2*tailLength);
+    % project
+    h(Os) = g(Os).*f(Os) + g(fliplr(Os)).*f(fliplr(Os));
+    h(Oe) = g(Oe).*f(Oe) - g(fliplr(Oe)).*f(fliplr(Oe));
+end
\ No newline at end of file