function s2mdet(infname, k, silence, treshold, sh_note, tempo)
% waw -> midi
% s2mdet(infname, k, silence, treshold, sh_note, tempo)
%
% Creates a MIDI file from WAV file
% 
% Input arguments:   INFNAME = input file name (*.wav)
%                    K = reduction konstatn for clipping
%                    SILENCE = level of silence
%                    TRESHOLD = treshold for ACF
%                    SH_NOTE = shortest note
%                    TEMPO = bpm, beats per minute (default 120)
%                               
% Example: sound2midi('samp.wav', 0.2, 0.015, 0.7, 32, 100)
%          creates samp.mid from samp.wav wiht the shortest note 1/32
%          tempo = 100   

if isempty(nargin), error('No imput arguments'); end
if nargin < 2, k = 0.2; end
if nargin < 3, silence = 0.015; end
if nargin < 4, treshold = 0.7; end
if nargin < 5, sh_note = 32; end
if nargin < 6, tempo = 120; end

outfname = [infname(1:end-4) '.mid'];
% loads input wav file
[samp, Fs, bits] = wavread(infname);

% divides tempo to 3 bytes
tmp = dec2bin(tempo, 24);
tmp1 = bin2dec(tmp(1 : 8));
tmp2 = bin2dec(tmp(9 : 16));
tmp3 = bin2dec(tmp(17 : 24));

% creates MThd_chunk headr
MThd_chunk = [77 84 104 100 0 0 0 6 0 0 0 1 1 192]; %14 bytes        

% creates track_chunk headr
MTrk_chunk = [77 84 114 107 0 0 0 0];% 255 51 3 tmp1 tmp2 tmp3];

headr = [MThd_chunk MTrk_chunk];

fid = fopen(outfname, 'w');
if fid == -1, error('Could not create otput file'); end

% wtires headr into midi file
count = fwrite(fid, headr);
if count ~= length(headr), error('Could not write headr to output file'); end
st = fclose(fid);
if st == -1, error('Could not close output file'); end

% creates frequency -> midi note number conversion chart
for n = 0 : 127
    f = 440 * 2 ^ ((n - 69) / 12);                            
    fr_tab(n + 1) = round(f);
end

% opens file for attachment of midi event
fid = fopen(outfname,'a');
if fid == -1, error('Could not open output file'); end

% win = lenth of win from which the frequenci is being detected
win = round(Fs * ((4 * (1 / sh_note) * 60) / tempo));

% time of one work window in miliseconds
win_time = (win + 1) * 1/Fs * 1000;

%segmentation of input signal
segments = cntrclip(segment(samp, win), k, silence);

%deciding what is row and what is column :-)
len = length(segments(:,1));
[m n] = size(segments);
if m == len, rows = n;
else rows = m; end

% inicialization of counters etc.
m = 4;
cntr = 0;
n(1:4) = 0;

% the heart of whole function :-)
for i = 1 : rows
    % finds frequency of analyzed signal
    buff = fft(segments(:,i),4096);
    buff = buff .* conj(buff);
    buff = ifft(buff);
    buff = buff(1:end/2);
    firstmax = max(buff);
    buff(treshold*firstmax > buff) = 0;
 
    if find(buff>0)
        lag = 2; ind = 1; p = 1; q = 2;
        while lag(q-1) > 1
            if p == 1, lag(p)=0; end
            if ~isnan(find(buff((sum(ind)+sum(lag)):end) == 0,1, 'first'))
                ind(p) = find(buff((sum(ind)+sum(lag)):end) == 0,1, 'first');
                if(sum(ind)+sum(lag)) <= length(buff)
                    [M(p) lag(p)] = max(buff(sum(ind)+sum(lag):end));
                    p = p + 1; q = p;
                else
                    buff(1:end) = 1;
                end
            else
                lag(p) = 0;
                p = p + 1; q = p;
            end
        end
        
        if p>2
            freq(i) = Fs/((sum(ind)+sum(lag)-ind(p-2)-1)/(p-2));
        else
            freq(i) = 0;
        end
    else
        freq(i) = 0;
    end
 
    [min_diff, n(m)] = min(abs(fr_tab - freq(i)));
    n(m) = n(m) - 1;
 
    % writes midi event
 
    if (n(m) == n(m - 1)) || (n(m) < 30) || (n(m) > 95)% || (delta < sh_note)
	cntr =cntr + 1;

    else

        if n(m - 1) ~= n(m - 2), cntr = 1; end
        delta = round(win_time * cntr);
        bytes = encode_var_length(delta);     
        note_off =[bytes 144 n(m - 1) 0];
        count = fwrite(fid, note_off);            
        note_on = [0 144 n(m) 64];
        count = fwrite(fid, note_on);
        cntr = 0;
    end
     m = m + 1;
 
end

% writes end of track
delta = round(win_time * cntr);
bytes = encode_var_length(delta);    
end_of_track = [bytes 144 n(m - 1) 0 0 255 47 0];
count = fwrite(fid, end_of_track);

% closes writtn file
st = fclose(fid);
if st == -1, error('Could not close output file after all'); end

% writes a length of MTrk
fid = fopen(outfname, 'r+');
if fid == -1, error('Could not open output file for write length of MTrk'); end
count = fread(fid );
len = length(count) - length(MThd_chunk) - 8;
tmp = dec2bin(len, 32);
tmp1 = bin2dec(tmp(1 : 8));
tmp2 = bin2dec(tmp(9 : 16));
tmp3 = bin2dec(tmp(17 : 24));
tmp4 = bin2dec(tmp(25 : 32));
tmp = [tmp1 tmp2 tmp3 tmp4];
st = fseek(fid, 18, -1);
if st == -1, error('Could not set the offset'); end
count = fwrite(fid, tmp );
if count ~= 4, error('Faild to write length of MTrk'); end
st = fclose(fid);
if st == -1, error('Closing output file faild'); end

% converts dec to be written as variable length quantity
function bytes = encode_var_length(val)

binStr = dec2base(round(val), 2);
Nbytes = ceil(length(binStr) / 7);

binStr = ['00000000' binStr];
bytes = [];
for i = 1 : Nbytes
  if (i == 1)
    lastbit = '0';
  else
    lastbit = '1';
  end
  B = bin2dec([lastbit binStr(end - i  * 7 + 1 : end - (i - 1) * 7)]);
  bytes = [B bytes];
end