
function T = dttmtxno(N,type,frwd,symv)
% DTTMTX Discrete trigonometric transform matrix (non-orthogonal)
%   T = dttmtxno(N,type,frwd,symv)
%
%   This generates all 16 DTT transformation matrices
%
%   N:    transform size (NxN)
%   type: dtt type. Here are all the possible types:
%         'dct1e','dct2e','dct3e','dct4e'
%         'dct1o','dct2o','dct3o','dct4o'
%         'dst1e','dst2e','dst3e','dst4e'
%         'dst1o','dst2o','dst3o','dst4o'
%   frwd: if set the forward transform is calculated otherwise
%         the inverse.  this is necessary cause on non-orthogonality
%   symv: if this flag is set then a symbolic matrix is produced
%         used for various proofs
%   T:    the transformation matrix
%
%   Notes: The implementation generates non orthogonal DTT matrices.
%          as defined by Martucci
%
%   Example:
%   Transforming an framed input signal x (frame per column)
%   can be done as:
%   [N,M] = size(x);
%   T = dttmtxno(N,'dct2e'); % Type II even
%   X = T*x;
%
%   Reference: S.A. Martucci, "Symmetric convolution and the discrete
%              sine and cosine transforms", IEEE Trans. Sig. Processing
%              SP-42, pp1038-1051, 1994

% ------- dttmtxno.m ---------------------------------------
% Marios Athineos, marios@ee.columbia.edu
% http://www.ee.columbia.edu/~marios/
% Copyright (c) 2005 by Columbia University.
% All rights reserved.
% ----------------------------------------------------------

% The default DTT type is the forward DCT type II even
if nargin < 2; type = 'dct2e'; end
if nargin < 3; frwd = 1;       end
if nargin < 4; symv = 0;       end

% Make the indices n (time) and m (frequency) ...
[m,n]   = ndgrid(0:N-1);

% ... and the scaling factors
k      = ones(N,1);
k(1)   = 1/2;
l      = ones(N,1);
l(end) = 1/2;

% Make k,l diagonal matrices so that we can
% left / right multiply the kernel.  This is
% not computationaly efficient but it shows
% nicelly how the weights are applied.
k = diag(k);
l = diag(l);

% If the flag is setc convert stuff to
% symbolic and we are all set
if symv
    N = sym(N);
    m = sym(m); n = sym(n);
    k = sym(k); l = sym(l);
end

% Make the transformation matrix
switch lower(type)
    % ----------------------------------------------------
    % DCT I-IV even
    case {'dctie',  'dct1e'}
        N = N-1; k(end) = k(1);
        T = 2    *cos( m     .* n     *pi /N) *k;
    case {'dctiie', 'dct2e'}
        T = 2    *cos( m     .*(n+.5) *pi /N);
    case {'dctiiie','dct3e'}
        T = 2    *cos((m+.5) .* n     *pi /N) *k;
    case {'dctive', 'dct4e'}
        T = 2    *cos((m+.5) .*(n+.5) *pi /N);
    % ----------------------------------------------------
    % DCT I-IV odd
    case {'dctio',  'dct1o'}
        T = 2    *cos( m     .* n     *2 *pi /(2*N-1)) *k;
    case {'dctiio', 'dct2o'}
        T = 2    *cos( m     .*(n+.5) *2 *pi /(2*N-1)) *l;
    case {'dctiiio','dct3o'}
        T = 2    *cos((m+.5) .* n     *2 *pi /(2*N-1)) *k;
    case {'dctivo', 'dct4o'}
        N = N+1;
        T = 2    *cos((m+.5) .*(n+.5) *2 *pi /(2*N-1));
    % ----------------------------------------------------
    % DST I-IV even
    case {'dstie',  'dst1e'}
        m = m+1; n = n+1; N = N+1;
        T = 2    *sin( m     .* n     *pi /N);
    case {'dstiie', 'dst2e'}
        m = m+1;
        T = 2    *sin( m     .*(n+.5) *pi /N);
    case {'dstiiie','dst3e'}
        n = n+1; k(end) = k(1); k(1) = 1;
        T = 2    *sin((m+.5) .* n     *pi /N) *k;
    case {'dstive', 'dst4e'}
        T = 2    *sin((m+.5) .*(n+.5) *pi /N);
    % ----------------------------------------------------
    % DST I-IV odd
    case {'dstio',  'dst1o'}
        m = m+1; n = n+1; N = N+1;
        T = 2    *sin( m     .* n     *2 *pi /(2*N-1));
    case {'dstiio', 'dst2o'}
        m = m+1; N = N+1;
        T = 2    *sin( m     .*(n+.5) *2 *pi /(2*N-1));
    case {'dstiiio','dst3o'}
        n = n+1; N = N+1;
        T = 2    *sin((m+.5) .* n     *2 *pi /(2*N-1));
    case {'dstivo', 'dst4o'}
        T = 2    *sin((m+.5) .*(n+.5) *2 *pi /(2*N-1)) *l;
    % ----------------------------------------------------
    otherwise
        error('Unknown DTT type, try dct2e.  help dttmtx for a full list.')
end

% Calculate the scale factor for inverse
if ~frwd
    switch lower(type(end))
        case 'e'
            N = 2*N;
        case 'o'
            N = 2*N-1;
    end
    % Apply the scale factor
    T = T/N;
end