function s2mspec(infname, sh_note, tempo, level)
% waw -> midi
% s2mspec(infname, sh_note, tempo, level)
%
% Creates a MIDI file from WAV file
% 
% Input arguments:   INFNAME  = input file name (*.wav)
%                    SH_NOTE  = the shortest note (defaul demisemiquaver 
%                               -> 1/32)                 
%                    TEMPO    = bpm, beats per minute (default 120)
%                    LEVEL    = level for half frequency detection
%                                                   
% Example: sound2midi('samp.wav', 32, 100, 0.5)
%          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, sh_note = 32; end
if nargin < 3, tempo = 120; end
if nargin < 4, level = 0.5; end

%creates output name
outfname = [infname(1:end-3) '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];        

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

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

% wtires headr of 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);                            
    freq(n + 1) = round(f);
end

% creates intensity -> velocity conversion chart
vel = logspace(1, 3, 128);
vel = vel / max(vel);

% 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;

% marks frequency axis
f = Fs / 2 * linspace(0, 1, 4096 / 2);

%silence = level of silence
silence = 0.1;

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

%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 = 3;
cntr = 0;
han = hann(win);
n(1:4) = 0;
ftest(1:2) = 0;
% reads a window of samples
for i = 2 : rows
    buff = segments(:,i) .* han;
    velocity(m) = max(buff);
        
    if velocity(m) > silence
        [vel_diff(m), velocity(m)] = min(abs(vel - velocity(m)));
        buff = fft(buff, 4096);
        buff = buff(1:end/2) .* conj(buff(1:end/2));
        % finds frequency of analyzed signal
        [M l] = max(buff);        
        half = floor(l/2);
        if half>1
            if (buff(half) > level*M)
                ftest(i) = round(f(floor(l/2)));
            else
                ftest(i) = round(f(l));
            end
        else
            ftest(i) = round(f(l));
        end
        
    else
        ftest(i) = 0;
    end
    [min_diff, n(m)] = min(abs(freq - ftest(i)));
    n(m) = n(m) - 1;
    % conditions of relevant input signal
    if (n(m) == n(m - 1)) || (n(m) < 55) || (n(m) > 95)
	cntr =cntr + 1;
	
    else
        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