function reconstructed=SMALL_midiGenerate(V, Problem)
%%% Reconstraction of midi file from representation in the given dictionary
%
%   Centre for Digital Music, Queen Mary, University of London.
%   This file copyright 2009 Ivan Damnjanovic.
%
%   This program is free software; you can redistribute it and/or
%   modify it under the terms of the GNU General Public License as
%   published by the Free Software Foundation; either version 2 of the
%   License, or (at your option) any later version.  See the file
%   COPYING included with this distribution for more information.
%   
%   SMALL_midiGenerate is a part of SMALLbox and can be use to reconstruct
%   a midi file given representation of the training set (V) in the
%   dictionary Problem.A.
%   Output is reconstructed structure with two fields:
%   -   reconstructed.notes - matrix with transcribed notes
%   -   reconstructed.midi - midi representation of transcription

%%
U=Problem.A;    %   Dictionary used for representation
fs=Problem.fs;  %   Sampling rate
f=Problem.f;    %   vector of frequencies at wihch spectrogram is computed

ts=(Problem.windowSize*Problem.overlap)/fs; %size of an analysis frame in seconds

%%
% Components pitch estimation using modified SWIPE algorithm by Arthuro
% Camacho
% 
% Columns of matrix U are spectrograms of the notes learned from the
% training set. We are estimating pitches of these notes by also
% restricting pitch values to the one of the 88 piano notes. 

pitch=zeros(size(U,2),1);

for i=1:size(U,2)
    
    pitch(i) = SMALL_swipe(U(:,i),fs, f, [27.50 8192], 1/12);
    
end

%%
% If some of columns of U have the same pitch, their contribution to the
% score (matrix V) is summed.

[Ps,idx]=sort(pitch);
ndp=1;
Pd(ndp)=Ps(1);
Vnew(ndp,:)=V(idx(1),:);
for i=2:88
    if Ps(i)> Ps(i-1)
        
        ndp=ndp+1;
        Vnew(ndp,:)=V(idx(i),:);
        Pd(ndp)=Ps(i);
        
    else
        Vnew(ndp,:)=Vnew(ndp,:)+V(idx(i),:);
    end
end
%%
% Generate midi matrix

midx=0;
for i=1:ndp
    
    %   Threshold for finding onsets and offsets of notes
    
    thr=mean(Vnew(i,:));%+std(Vnew(i,:));
    
    if(Pd(i)~=0)
        for j=1:size(Vnew,2)
            if Vnew(i,j)<thr
                Vnew(i,j)=0;
                if(j>1)
                    if (Vnew(i,j-1)==1)
                        try
                            M(midx,6)=(j-1)*ts;
                            if (M(midx,6)-M(midx,5))<2*ts
                                midx=midx-1;
                            end
                        catch
                            pause;
                        end
                    end
                end
            else
                Vnew(i,j)=1;
                if(j>1)
                    if (Vnew(i,j-1)==0)
                        midx=midx+1;
                        M(midx,1)=1;
                        M(midx,2)=1;
                        M(midx,3)=69 +round( 12 *log2(Pd(i)/440));
                        M(midx,4)=80;
                        M(midx,5)=(j-1)*ts;
                    end
                else
                    midx=midx+1;
                    M(midx,1)=1;
                    M(midx,2)=1;
                    M(midx,3)=69 + round(12 *log2(Pd(i)/440));
                    M(midx,4)=80;
                    M(midx,5)=0;
                end
            end
        end
        if M(midx,6)==0
            M(midx,6)=(j-1)*ts;
        end
    end
end

M=sortrows(M,5);
reconstructed.notes=M;
reconstructed.midi = matrix2midi(M);